小小的状压dp
直接考虑维护一个
然后直接转移就好啦。。。。过水
不过细节比较多。。。比较难写?
#include<bits/stdc++.h>
#define MAXN 1000
#define maxn 1000005
using namespace std;
int T;
int n;
int t[MAXN+5],b[MAXN+5];
int f[MAXN+5][1<<9][35];
//f[i][j][s]前i-1个人已取完菜,上一次取的菜同学里i距离是j,i----b[i]的状态是s
//会出现负数,于是要加上8
void init(){
cin>>n;
for(int i = 1 ; i <= n ; i++)cin>>t[i]>>b[i];
memset(f , 0x7f , sizeof(f));
}
//f[i][s][j]---->f[i+1][s>>1][j + 7]
//f[i][s][j]---->f[i][在s里面把k标上][k]
void solve(){
f[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(f[i][j][k + 8]<maxn){
if(j & 1){f[i + 1][j>>1][k + 7] = min(f[i + 1][j>>1][k + 7] , f[i][j][k + 8]);}
else{
int minl = maxn;
for(int l = 0 ; l <= 7 ; l++){
if(!((j>>l)&1)){
if(l + i > minl)break;
minl = min(minl , i + l + b[i + l]);
f[i][j | (1<<l)][l + 8] = min(f[i][j | (1<<l)][l + 8] , f[i][j][k + 8] + ((i + k)?(t[i + k]^t[i + l]):0));
}
}
}
}
}
int maxl = maxn;
for(int i = 0 ; i <= 8 ; i++)maxl = min(maxl , f[n + 1][0][i]);
cout<<maxl<<endl;
}
int main(){
cin>>T;
while(T--){
init();
solve();
}
}