BZOJ1226 SDOI2009学校食堂(状压dp)
生活随笔
收集整理的這篇文章主要介紹了
BZOJ1226 SDOI2009学校食堂(状压dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
由于Bi<=7,考慮狀壓。
如果考慮前i個位置的話,狀態里需要壓入前7個人后7個人,顯然是跑不動的。
那么改成考慮前i個人。于是設f[i][j][k]表示前i個人都已吃完飯,i+1后面7個人的吃飯狀態為j,最后一個吃飯的人是k的答案。轉移時考慮下一個吃飯的是誰即可。
a|b-a&b=a^b。當然沒什么用。
各種情況需要考慮的非常清楚。寫的跟我一樣丑的話就比較難搞了。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() {int x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f; } #define N 1010 int T,n,a[N],b[N],f[N][1<<7][16],lg2[1<<7|1],l[7]; int main() { #ifndef ONLINE_JUDGEfreopen("bzoj1226.in","r",stdin);freopen("bzoj1226.out","w",stdout);const char LL[]="%I64d\n"; #elseconst char LL[]="%lld\n"; #endifT=read();for (int i=0;i<=7;i++) lg2[1<<i]=i;while (T--){int n=read();for (int i=1;i<=n;i++) a[i]=read(),b[i]=read();memset(f,42,sizeof(f));f[0][0][7]=0;for (int i=0;i<n;i++)for (int j=0;j<(1<<min(7,n-i-1));j++){l[0]=min(i+1+b[i+1],n);for (int k=1;k<7;k++)if (!(j&(1<<k-1))) l[k]=min(l[k-1],i+k+1+b[i+k+1]);else l[k]=l[k-1];for (int k=0;k<16;k++)if (k<=7&&i+k-7>=0||k>=9&&(j&(1<<k-9))){f[i+1+lg2[j+1&-(j+1)]][j>>lg2[j+1&-(j+1)]+1][7-lg2[j+1&-(j+1)]]=min(f[i+1+lg2[j+1&-(j+1)]][j>>lg2[j+1&-(j+1)]+1][7-lg2[j+1&-(j+1)]],f[i][j][k]+(i+k-7?(a[i+k-7]^a[i+1]):0));for (int x=1;x<=7;x++)if (!(j&(1<<x-1))&&i+x+1<=l[x-1])f[i][j|(1<<x-1)][8+x]=min(f[i][j|(1<<x-1)][8+x],f[i][j][k]+(i+k-7?(a[i+k-7]^a[i+x+1]):0));}}for (int i=1;i<8;i++) f[n][0][0]=min(f[n][0][0],f[n][0][i]);cout<<f[n][0][0]<<endl;}return 0; }?
轉載于:https://www.cnblogs.com/Gloid/p/9639870.html
總結
以上是生活随笔為你收集整理的BZOJ1226 SDOI2009学校食堂(状压dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何用“云崽(Yunzai)”搭建一个原
- 下一篇: Object o = new Objec