<SDOI2009>学校食堂
我.
调了快一天
因为一个位置错误的感叹号
:-)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
狗dp
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 99999999 using namespace std; int c,n; int t[1005],b[1005],dp[1005][1<<9][20];//dp 前i-1个人已经打完饭了,第i个人及其后面7个人的状态,上一次打饭的人与i的相对距离(向前为-向后为+) 实际运用时由于不能为负数 所以要+8 int time(int a,int b){if(a==0)return 0; return t[a]^t[b];}//题目要求的时间计算 int main() { int i,j,k; scanf("%d",&c); for(int l=1;l<=c;l++) { scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d%d",&t[i],&b[i]); for(i=1;i<=n+1;i++) for(j=0;j<(1<<8);j++) for(k=-8;k<=7;k++) dp[i][j][k+8]=inf; dp[1][0][7]=0;// k -1+8 //初始化 for(i=1;i<=n;i++)//枚举n个人 for(j=0;j<(1<<8);j++)//枚举状态 for(k=-8;k<=7;k++)//枚举相对位置 if(dp[i][j][k+8]<inf)//没轮到呢.怎么排他后面的...?! { if(j&1) dp[i+1][j>>1][k+7]=min(dp[i+1][j>>1][k+7],dp[i][j][k+8]);else//如果已经打完了 就可以 扔了emm 下一个还未打的时间与上一个打完时间相同 { int r=inf;//忍受范围 for(int m=0;m<=7;m++)//枚举下一个人 { if(!((j>>m)&1))//判断后面的人是否吃完了 { if(i+m>r)break;//超出了忍耐限度! r=min(r,i+m+b[i+m]);//更新目前最小忍耐限度 dp[i][j+(1<<m)][m+8]=min(dp[i][j+(1<<m)][m+8],dp[i][j][k+8]+time(i+k,i+m));//emm让他有饭(雾 } } } } int ans=inf; for(i=0;i<8;i++)ans=min(ans,dp[n+1][0][i]);//全部人都有饭啦! printf("%d\n",ans); } return 0; }