BZOJ1226: [SDOI2009]学校食堂Dining

时间:2022-11-28 04:31:30

inf、数组开小了,细节处理的不好


可以发现 a or b-a and b = a xor b ,不过这和这题解法没太大关系233

观察数据范围,发现Bi ≤ 7
那么说明每个人拿到饭菜的顺序不会提前7位以上,不会滞后7位以上
所以我们用f i j k 表示1~i-1 拿完了饭,j表示i~i+7拿饭的情况,k表示上一个拿饭的和i的位置关系,注意k的范围是-8~7,f是最少的时间
转移的话,
如果i已经拿了饭,直接向f i+1,j>>1,k-1转移
然后枚举一下下一个谁拿饭

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define f(i,j,k) f[i][j][k+8]
using namespace std;

inline int read()
{
char c; int x;
while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
return x;
}
inline void up(int &x,const int &y){if(x<y)x=y;}
inline void down(int &x,const int &y){if(x>y)x=y;}
const int maxn = 1100;
const int maxb = 1<<8;
const int inf = 1024001;

int f[maxn][maxb][16];
int n,m;
int ti[maxn],bi[maxn];

inline int cal(int x,int y){return x==0?0:ti[x]^ti[y];}

int main()
{
int t=read();
while(t--)
{
n=read();
for(int i=1;i<=n;i++) ti[i]=read(),bi[i]=read();

memset(f,63,sizeof f); f(1,0,-1)=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<maxb;j++)
for(int k=-8;k<=7;k++) if(f(i,j,k)<inf)
{
if(j&1) down(f(i+1,j>>1,k-1),f(i,j,k));
int nex=inf;
for(int l=0;l<=7&&i+l<=nex;l++) if(!(j&(1<<l)))
{
if(!l) down(f(i+1,j>>1,l-1),f(i,j,k)+cal(i+k,i+l));
else down(f(i,j|(1<<l),l),f(i,j,k)+cal(i+k,i+l));
down(nex,i+l+bi[i+l]);
}
}
}
int ans=inf;
for(int k=-8;k<=-1;k++) down(ans,f(n+1,0,k));
printf("%d\n",ans);
}

return 0;
}