題目:https://www.luogu.org/problemnew/show/P2577node
題意:n我的每一個人有一個打飯時間和吃飯時間,將他們分紅兩個隊伍。每一個人打到飯以後就立刻去吃飯。問怎麼安排可讓整體的吃飯時間最短。ios
思路:首先貪心仍是很好想的。某個隊伍的總吃飯時間其實是打飯結束+吃飯時間最晚的那個時間。spa
一個隊伍前面的那些人,若是他們吃完飯的時間都不超過總的排隊時間的話,根本不須要考慮他們。而隊伍的排隊時間若是安排好了,是固定的。跟安排的順序沒有關係。code
因此咱們應該要把吃飯時間長的往前放。由於排隊時間不受順序影響可是吃飯時間受順序的影響。blog
而後咱們能夠考慮怎麼給他們分紅兩隊。get
首先能夠考慮$dp[i][j][k]$表示考慮到第$i$我的,第一條隊伍排隊時間是$j$第二條隊伍排隊時間是$k$的時候,最先所有吃完飯的時間。string
可是咱們發現$j$和$k$存在關係,由於兩個隊伍總的排隊時間是固定的。因此咱們能夠用$sum[i]$來維護排隊時間的前綴和。就能夠減小一個維度了。it
因此咱們能夠用$dp[i][j]$表示考慮到第$i$我的,第一條隊伍排隊時間是$j$最先所有吃完飯的時間。此時顯然第二條隊伍的排隊時間是$sum[i] - j$io
因而有$dp[i][j] = min(max(dp[i-1][j-get[i]], j + eat[i]), max(dp[i - 1][j], sum[i] - j + eat[i]))$分別表示第$i$我的排在第一個隊伍和排在第二個隊伍。class
1 #include<cstdio> 2 #include<cstdlib> 3 #include<map> 4 #include<set> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<cmath> 9 #include<stack> 10 #include<queue> 11 #include<iostream> 12 13 #define inf 0x3f3f3f3f 14 using namespace std; 15 typedef long long LL; 16 typedef pair<int, int> pr; 17 18 int n; 19 const int maxn = 205; 20 struct node{ 21 int get, eat; 22 }stu[maxn]; 23 int sum[maxn]; 24 int dp[maxn][maxn * maxn * 2]; 25 26 bool cmp(node a, node b) 27 { 28 return a.eat > b.eat; 29 } 30 31 int main() 32 { 33 scanf("%d", &n); 34 memset(dp, 0x3f, sizeof(dp)); 35 for(int i = 1; i <= n; i++){ 36 scanf("%d%d", &stu[i].get, &stu[i].eat); 37 } 38 sort(stu + 1, stu + 1 + n, cmp); 39 40 for(int i = 1; i <= n; i++){ 41 sum[i] = sum[i - 1] + stu[i].get; 42 } 43 dp[0][0] = 0; 44 for(int i = 1; i <= n; i++){ 45 for(int j = 0; j <= sum[i]; j++){ 46 if(j >= stu[i].get)dp[i][j] = min(dp[i][j], max(dp[i - 1][j - stu[i].get], j + stu[i].eat)); 47 dp[i][j] = min(dp[i][j], max(dp[i - 1][j], sum[i] - j + stu[i].eat)); 48 } 49 } 50 51 int ans = inf; 52 for(int j = 0; j <= sum[n]; j++){ 53 ans = min(ans, dp[n][j]); 54 } 55 printf("%d\n", ans); 56 return 0; 57 }