洛谷2157 學校食堂(狀壓DP)
阿新 • • 發佈:2018-12-19
傳送門
【題目分析】
用命分析,這個資料範圍很狀壓。。。。。。然後就狀壓啊。
陣列dp[i][j][k]表示前i-1個人已經拿到菜,j列舉i以及他後面7個的拿菜情況,k表示上一個吃飯的位置(相對的)
注意一下列舉的上下界即可。
【程式碼~】
#include<bits/stdc++.h> using namespace std; const int MAXN=1e3+10; const int INF=0x3f3f3f3f; int T; int n,ans; int dp[MAXN][1<<9][20]; struct stu{ int x,y; }st[MAXN]; int Read(){ int i=0,f=1; char c; for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar()); if(c=='-') f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar()) i=(i<<3)+(i<<1)+c-'0'; return i*f; } int calc(int a,int b) { if(a==0) return 0; return st[a].x^st[b].x; } void solve() { for(int i=1;i<=n+1;i++){ for(int j=0;j<(1<<8);j++){ for(int k=-8;k<=7;k++){ dp[i][j][k+8]=INF; } } } dp[1][0][7]=0; for(int i=1;i<=n;i++){ for(int j=0;j<(1<<8);j++){ for(int 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][j][k+8],dp[i+1][j>>1][k+7]); } else{ int r=INF; for(int l=0;l<8;l++){ if(!(j&(1<<l))){ if(i+l>r) break; r=min(r,i+l+st[i+l].y); dp[i][j+(1<<l)][l+8]=min(dp[i][j+(1<<l)][l+8],dp[i][j][k+8]+calc(i+k,i+l)); } } } } } } } int main() { T=Read(); while(T--) { n=Read(); for(int i=1;i<=n;i++) st[i].x=Read(),st[i].y=Read(); solve(); ans=INF; for(int i=-8;i<0;i++) ans=min(dp[n+1][0][i+8],ans); cout<<ans<<'\n'; } return 0; }