首先,比較容易想到的一點是應該把所有人按吃飯時間從大到小排個序,讓吃飯時間長的人優先打飯,這樣會是最優的。
其次,設f[i][j][k]表示前i個人在一號隊打飯時間為j二號隊打飯時間為k時的總時間的最優解(有點繞),於是乎,轉移方程就是
$ f[i][j][k] = min(max(f[i-1][j-a[i]][k], j+b[i]), max(f[i-1][j][k-a[i]], k+b[i])) $
但是考慮到空間會炸,需要進行優化。可以預處理出前i個人打飯時間總和sum[i],那麼我們便可以得出 $ k = sum[i] - j $ 。這樣一來,就可以轉化成f[i][j]表示前i個人在一號隊打飯時間為j時的總時間的最優解,$ f[i][j] = min(max(f[i-1][j-a[i]], j+b[i]), max(f[i-1][j], sum[i]-j+b[i])) $
code:
#include #include #include #include using namespace std;
//mystery_sky
//#define m 1000
#define inf 0x3f3f3f3f
#define ll long long
inline int read()
while(c>='0'&&c<='9')
return x*f;
}struct nodepeo[m];
inline bool cmp(node x, node y)
int f[201][40000], sum[201];
int n, ans = inf;
int main()
} for(int i = 1; i <= sum[n]; i++) if(f[n][i]) ans = min(ans, f[n][i]);
printf("%d\n", ans);
return 0;
}
洛谷 P2577 ZJOI2005 午餐
這道題目比較難想。演算法 貪心 dp 容易想到貪心 吃飯慢的先打飯節約時間,所以先將人按吃飯時間從大到小排序。然後就是dp了 首先,應該想到f i j k 前i個人,在1號視窗打飯總時間j,在2號視窗打飯總時間k 當然,這樣會爆空間,所以想到去掉一維。f i j 表示前i個人,在1號視窗打飯總時間j...
洛谷P2577 ZJOI2005 午餐
挺棒的一道dp。貪心策略容易想到。直接按吃飯時間從大到小排序即可。重點是dp。可以設方程為 f 前 i 人 佇列1的時間 j 然後加上乙個常見的滾動陣列套路。方程的轉移還是很有意思。include include include include using namespace std const i...
題解 P2577 ZJOI2005 午餐
題目大意 每個人有乙個打飯時間和吃飯時間,求把所有人分到兩個隊伍,所有人都吃完飯的最短時間 動態規劃,貪心 分析 既然每個人有乙個吃飯時間和打飯時間,我們可以大膽猜想,讓吃的慢的人先打飯 我有乙個比較迷的證明,不知道對不對 假如只有乙個佇列,設打飯時間為 a 吃飯時間為 b ans max a j ...