标签:方案 时间 集合 师傅 microsoft 输出 string har clu
方案如下:
窗口1: 窗口2:
7 7 1 3
6 4 8 5
2 2
【限制】
所有输入数据均为不超过200的正整数。
题解:首先自己讨论一下就能知道,如果只有一个队列,那么一定是让吃饭时间慢的先打饭。那么如果有两个队列,那么其中的每一个都一定是按吃饭时间递减的,所以我们先将所有人按吃饭时间排序。
然后设f[i][j][k]表示前i个人,A队列总等待时间为j,B队列总等待时间为k,所需要的最小总时间。下一步比较神,用sum[i]表示前i个人等待时间的前缀和,则j+k=sum[i],所以我们可以优化掉一维。
然后就容易DP了。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int n,ans; int f[1010][260][17],cnt[260],T[1010],B[1010]; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } int calc(int a,int b) { if(a<=0) return 0; return T[a]^T[b]; } void work() { memset(f,0x3f,sizeof(f)); n=rd(); int i,j,k,l; for(i=1;i<=n;i++) T[i]=rd(),B[i]=min(rd(),n-i); f[0][0][8]=0; for(i=0;i<n;i++) for(j=0;j<(1<<min(n-i,8));j++) for(k=max(8-i,0);k<=min(n-i,8)+8;k++) { if(j&1) { f[i+1][j>>1][k-1]=min(f[i+1][j>>1][k-1],f[i][j][k]); continue; } int lim=min(n-i,8); for(l=1;l<=lim;l++) if(!(j&(1<<(l-1)))) { f[i][j|(1<<(l-1))][l+8]=min(f[i][j|(1<<(l-1))][l+8],f[i][j][k]+calc(i+k-8,i+l)); lim=min(lim,l+B[i+l]); } } ans=1<<30; for(i=max(8-n,0);i<=8;i++) ans=min(ans,f[n][0][i]); printf("%d\n",ans); } int main() { int T=rd(); while(T--) work(); return 0; }//1 2 5 0 4 0
【BZOJ1899】[Zjoi2004]Lunch 午餐 贪心+DP
标签:方案 时间 集合 师傅 microsoft 输出 string har clu
原文地址:http://www.cnblogs.com/CQzhangyu/p/7468822.html