1. 程式人生 > >【BZOJ1899】午餐(動態規劃)

【BZOJ1899】午餐(動態規劃)

需要 記錄 表示 列隊 其中 truct ble read namespace

【BZOJ1899】午餐(動態規劃)

題面

BZOJ

題解

我太弱了
這種\(dp\)完全做不動。。

首先,感性理解一些
如果所有人都要早點走,
那麽,吃飯時間長的就先吃
吃飯時間短的就晚點吃
所以,按照吃飯時間排序

我們不難得出一個每個人吃完飯的時間
之和前面所有人的打飯的時間和有關
所以
\(f[i][j][k]\)表示當前做到第\(i\)個人,第一列,第二列前面的人的打飯時間之和分別為\(j,k\)時,最後一個人吃完飯的最小時間
因為人的順序我們是知道的
所以\(j+k\)是一個定值,是所有人打飯時間的前綴和
因此我們只需要記錄其中一個

所以,狀態是\(f[i][j]\)表示當前做到第\(i\)

個人,
第一列隊伍前面所有人打飯的時間和是\(j\)
最後一個人吃完飯的最小時間

如果把這個人放在第一列
\(f[i][j]=min(f[i][j],max(f[i-1][j-Get[i]],j+eat[i]))\)
這個應該不難理解
另外一個,把這個人放在第二列
\(f[i][j]=max(f[i-1][j],sum[i]-j+eat[i])\)

這題應該是一個很顯然的\(dp\)
但是我卻做不出來
我果然太弱了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define MAX 210 inline int read() { int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if
(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Peo{int a,b;}p[MAX]; int s[MAX],ans=2e9; int f[MAX][MAX*MAX],n; bool operator<(Peo a,Peo b) { if(a.b!=b.b)return a.b>b.b; else return a.a>b.a; } int main() { n=read(); for(int i=1;i<=n;++i)p[i].a=read(),p[i].b=read(); sort(&p[1],&p[n+1]); for(int i=1;i<=n;++i)s[i]=s[i-1]+p[i].a; memset(f,63,sizeof(f)); f[0][0]=0; for(int i=1;i<=n;++i) { for(int j=s[i-1];j>=0;--j) { f[i][j+p[i].a]=min(f[i][j+p[i].a],max(f[i-1][j],j+p[i].a+p[i].b)); f[i][j]=max(f[i-1][j],s[i-1]-j+p[i].a+p[i].b); } } for(int i=0;i<=s[n];++i)ans=min(f[n][i],ans); printf("%d\n",ans); return 0; }

【BZOJ1899】午餐(動態規劃)