标签:mem 贪心 desc sum 师傅 bool 不同的 ... 方案
方案如下:
窗口1: 窗口2:
7 7 1 3
6 4 8 5
2 2
【限制】
所有输入数据均为不超过200的正整数。
这题没有自己想出来QAQ
事实上如果只有一个窗口那就是经典贪心题,对吃饭时间进行排序,吃饭时间长的先打饭(因为总的打饭时间是一定的)
先保留上面的想法,想想其他做法
我们可以设$f[i][j][k]$表示前i个人在1窗口打饭时间为j,在2窗口打饭为k的最优解
但是j和k这两维都得开到40000(200*200)
考虑优化空间。发现只要对打饭时间维护一个前缀和,那么就可以只保存一个时间了,另外一个时间则是$sum[i]-j$
考虑转移(方程里面的c[i]是前缀和)
对于在1窗口打饭的情况:$f[i][j]=min(f[i][j],max(f[i-1][j-a[i].x],j+a[i].y))$
对于在2窗口打饭的情况:$f[i][j]=min(f[i][j],max(f[i-1][j],c[i]-j+a[i].y))$
那么最优解就是在$f[n][1...c[n]]$里面找了
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; struct node { int x,y; }a[300]; int h1,h2,n; int c[300],f[300][40000]; //f[i][j]表示前i个人时其中一个队伍打饭时间为j的最优解 //c数组维护前缀和 bool cmp(node a,node b){ return a.y>b.y; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i].x,&a[i].y); } memset(f,0x3f,sizeof(f)); sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++)c[i]=c[i-1]+a[i].x; f[0][0]=0; for(int i=1;i<=n;i++){ for(int j=0;j<=c[i];j++){ f[i][j]=min(f[i][j],max(f[i-1][j],c[i]-j+a[i].y)); //在另外一个窗口吃 if(j-a[i].x>=0)f[i][j]=min(f[i][j],max(f[i-1][j-a[i].x],j+a[i].y)); //在当前窗口吃 } } int ans=0x3f3f3f3f; for(int i=0;i<=c[n];i++){ ans=min(ans,f[n][i]); } printf("%d\n",ans); return 0; }
标签:mem 贪心 desc sum 师傅 bool 不同的 ... 方案
原文地址:https://www.cnblogs.com/henry-1202/p/9567319.html