BZOJ 1226: [SDOI2009]学校食堂Dining

14 篇文章 0 订阅
1 篇文章 0 订阅

状压DP
然而我一开始没!有!想!粗!来!
只好参(chao)考(xi)神犇的思路。。
大致是酱的
f(i,j,k) f ( i , j , k ) 表示前 i1 i − 1 个人已经吃了饭,且在 i i 之后的状态为j的人也吃了饭(用二进制表示后面的状态),最后吃的那个人是 i i 之后的第k
(注意 k k 可以是负数)
然后
如果j& 1=1 1 = 1 那么就表明第 i i 个人也是吃了的,所以可以转移到f(i+1,j>>1,k1)
否则就枚举下一个吃饭的人,转移到 f(i,j+1<<l,l) f ( i , j + 1 << l , l )
这么看也不是很难吧哈。。


#include<cstdio>
#include<cstring>
#include<algorithm>
#define g getchar()
#define f(i,j,k) ge[i][j][k+8]
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
inline ll read(){
    ll x=0,f=1;char ch=g;
    for(;ch<'0'||ch>'9';ch=g)if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=g)x=x*10+ch-'0';
    return x*f;
}
inline void out(ll x){
    int a[25],wei=0;
    if(x<0)putchar('-'),x=-x;
    for(;x;x/=10)a[++wei]=x%10;
    if(wei==0){puts("0");return;}
    for(int j=wei;j>=1;--j)putchar('0'+a[j]);
    putchar('\n');
}
int t[1005],Q,ge[1005][257][17],n,b[1005],ans;
int clear(){memset(ge,inf,sizeof(ge));}
inline int sum(int x,int y){return x==0?0:t[x]^t[y];}
//这里说明一下,根据容斥原理,a|b-a&b=a^b,不信可以手算几个
int main(){
//  freopen("","r",stdin);
//  freopen("","w",stdout);
    Q=read();
    for(;Q--;){
        clear();
        n=read();
        for(int i=1;i<=n;++i)t[i]=read(),b[i]=read();
        f(1,0,-1)=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)<inf){
            if(j&1)f(i+1,j>>1,k-1)=min(f(i+1,j>>1,k-1),f(i,j,k));
            else{
                int lim=inf;//lim是限制,就是防止超出了后面人的要求
                for(int l=0;l<=7;++l)
                if(!(j&(1<<l))){
                    if(i+l>lim)break;
                    lim=min(lim,i+l+b[i+l]);
                    f(i,j+(1<<l),l)=min(f(i,j+(1<<l),l),f(i,j,k)+sum(i+k,i+l));
                }
            }
        }
        ans=inf;
        for(int i=-8;i<=7;++i)ans=min(ans,f(n+1,0,i));
        out(ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值