[bzoj1226]学校食堂Dining
状压dp,注意记上一个人的时候要记到负数(当前这个人之前)
- 代码
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int t[1010],b[1010];
int G[1010][500][16];
int n;
int calc(int a,int b){
if(a==0)return 0;
else return t[a]^t[b];
}
#define f(a,b,c) (G[a][b][c+8])
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&t[i],&b[i]);
memset(G,0x3f3f3f3f,sizeof(G));
f(1,0,-1)=0;
for(int i=1;i<=n;i++){
for(int st=0;st<1<<8;st++){
for(int k=-8;k<=7;k++)
if(f(i,st,k)!=INF){
if(st&1)f(i+1,st>>1,k-1)=min(f(i+1,st>>1,k-1),f(i,st,k));
else {
int r=INF;
for(int l=0;l<=7;l++){
if((st&(1<<l))==0){
if(i+l>r)break;
r=min(r,i+b[i+l]+l);
f(i,st|(1<<l),l)=min(f(i,st|(1<<l),l),f(i,st,k)+calc(i+k,i+l));
}
}
}
}
}
}
int ans=INF;
for(int k=-8;k<=1;k++){
ans=min(f(n+1,0,k),ans);
}
printf("%d\n",ans);
}
}