• bzoj1226/luogu2157 学校食堂 (状压dp)


    我们先约定:(左) 窗口_人人人人人 (右)

    可以发现,我们只需要知道最靠左的还没打饭的人 以及它身后7个人的状态 以及上一个打饭的人是谁

    因为他左面的就都打过了 右面7个人以后肯定还没打

    可以设f[i][j][k]表示这是第i个人,身后7个人的状态是j,上一个打饭的是k

    但其实上一个打饭的离他最远也就是8,所以可以只记i和k的差值,为了避免出负数再加个10之类的

    考虑怎么转移,有两种情况

    1.i身后的某个人打饭:找到j中是0的一位x,同时保证x左面的没打饭的人+这个人的容忍度<=x,也就是保证这个转移合法

    2.i自己打饭:找到i右面第一个是0的位置,转移到这个位置

    转移的时候更新一下k就好了

     1 #include<bits/stdc++.h>
     2 #define CLR(a,x) memset(a,x,sizeof(a))
     3 using namespace std;
     4 typedef long long ll;
     5 typedef pair<int,int> pa;
     6 const int maxn=1050,maxs=260,maxb=20;
     7 
     8 inline ll rd(){
     9     ll x=0;char c=getchar();int neg=1;
    10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*neg;
    13 }
    14 
    15 int N,v[maxn],f[maxn][maxs][maxb],b[maxn],bin[maxb];
    16 
    17 int gettime(int i,int j,int k){
    18     return (i+k-10)?(v[i+j]|v[i+k-10])-(v[i+j]&v[i+k-10]):0;
    19 }
    20 
    21 int main(){
    22     //freopen("","r",stdin);
    23     int i,j,k,l;
    24     bin[1]=1;for(i=2;i<=8;i++) bin[i]=bin[i-1]<<1;
    25     for(int T=rd();T;T--){
    26         N=rd();
    27         for(i=1;i<=N;i++)
    28             v[i]=rd(),b[i]=rd();
    29         for(i=N+1;i<=N+10;i++)
    30             b[i]=23333;
    31         CLR(f,127);
    32         f[1][0][9]=0;int ans=1e9+1;
    33         for(i=1;i<=N;i++){
    34             for(j=0;j<bin[b[i]+1];j++){
    35                 for(k=0;k<=10+b[i];k++){
    36                     if(f[i][j][k]>=1e9) continue;
    37                     int mi=23333333;
    38                     for(l=1;l<=b[i]&&l<=mi;l++){
    39                         if(!(j&bin[l])) f[i][j|bin[l]][l+10]=min(f[i][j|bin[l]][l+10],f[i][j][k]+gettime(i,l,k));
    40                         if(!(j&bin[l])) mi=min(mi,l+b[i+l]);
    41                     }
    42                     for(l=1;l<=b[i];l++)
    43                         if(!(j&bin[l])) break;
    44                     f[i+l][j>>l][10-l]=min(f[i+l][j>>l][10-l],f[i][j][k]+gettime(i,0,k));
    45                     if(i+l>N) ans=min(ans,f[i+l][j>>l][10-l]);
    46                 }
    47             }
    48         }
    49         printf("%d
    ",ans);
    50     }
    51     return 0;
    52 }
  • 相关阅读:
    两数之和
    IntelliJ IDEA为类和方法自动添加注释
    IDEA main 函数的快捷键
    Mac终端开启代理
    Pycharm节能模式
    使用正则表达式替换构造字典
    使用代理爬取微信文章
    利用 Scrapy 爬取知乎用户信息
    Scrapy选择器的用法
    Scrapy命令行基本用法
  • 原文地址:https://www.cnblogs.com/Ressed/p/9950312.html
Copyright © 2020-2023  润新知