BZOJ1226: [SDOI2009]学校食堂Dining

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值