• luogu 2157 [SDOI2009]学校食堂 状压dp


    题意:给定一个序列,每个位置有 $t_{i},b_{i}$ 两个属性,分别代表该点的权值,和 $i$ 后面只允许不超过 $i+b_{i}$ 在 $i$ 前打饭. 而每一次 $i$ 打饭的代价为 $上一个打饭位置t_{上一个打饭位置}$ ^ $t_{i}$

    求一种分配打饭的先后顺序,使得总代价最小.

    $b_{i}<=7,n<=10^3$

    由于 $b_{i}<=7$,很容易想到状压.

    假设当前打饭的最后一个位置为 $i$,那么 $1$~$(i-7)$ 的位置必然都要打完.

    所以,我们设状态 $f[i][S][j]$,即 $1$ 到 $(i-1)$ 已打完饭,$i$ 及后面 $7$ 个人是否打完饭的状态为 $S$,最后一次打饭的人是 $(i+j)$.

    显然,$-8<=j<=7$

    考虑转移:

    令 $2^k$&$S=2^k$ 表示这个位置已经打过饭,否则未打过.

    考虑当前有 $2^0$&$S$,说明 $i$ 位置已经打过饭了,则可以直接更新 $f[i+1][S>>1][j+1]$

    否则,我们需要枚举 $S$ 在二进制中的每一位.

    再维护一个 $mn$,表示枚举 $i$ 位及 $i$ 之前要求的最小右端点(由 $b[i]$ 限制)

    那么,如果当前要打饭的位置满足在右端点以内,则可以直接更新:$f[i+1][S|2^k][k]$

    然后顺便更新一下 $mn$ 即可.

    #include <bits/stdc++.h> 
    #define N 1005   
    #define inf 0x3f3f3f3f   
    #define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    using namespace std;
    int n;
    int t[N],b[N],f[N][1<<10][20];
    inline int Num(int x) { return x+8; }
    inline void getmin(int &a,int b)  { if(b<a) a=b; }
    void solve() 
    { 
    	// setIO("candy");     
    	int i,j,k,h;        
    	scanf("%d",&n); 
    	for(i=1;i<=n;++i)     scanf("%d%d",&t[i],&b[i]);        
    	memset(f,inf,sizeof(f)); 
    	f[1][0][Num(-1)]=0;                                  
        for(i=1;i<=n;++i)    
    	{
    	    for(j=0;j<(1<<8);++j)       
    		{           
    			for(k=-8;k<=7;++k) 
    			    if(f[i][j][Num(k)]!=inf) 
    				{
    					if (j&1) 
    					    getmin(f[i+1][j>>1][Num(k-1)],f[i][j][Num(k)]);
    					else 
    					{
    						int tmp=inf;
    						for (h=0;h<=7;++h) 
    							if (!((j>>h)&1)) 
    							{
    								if(i+h>tmp) break;
    								getmin(tmp,i+h+b[i+h]);
    								getmin(f[i][j|(1<<h)][Num(h)],f[i][j][Num(k)]+(i+k?(t[i+k]^t[i+h]):0));
    							}
    					}
                    } 
    		}
    	} 
    	int res=inf;   
    	for(i=0;i<=8;++i)   res=min(res, f[n+1][0][i]);       
    	printf("%d
    ",res);     
    }   
    int main() 
    {
    	int T; 
    	scanf("%d",&T); 
    	while(T--) solve();     
    }
    

      

  • 相关阅读:
    Ruby创始人谈Ruby的blocks和closure结构
    C语言字节对齐
    如今的开发者应了解哪些过去闻所未闻的新技能
    mongo下面总是缺少那么几个好用的工具试试这个吧MongoDB管理工具
    我们程序员为什么难晋升
    CMMI vs. Scrum vs. XP
    Rspec在Rails项目中的使用
    什么是Scrum?
    大型软件产品的敏捷案例 分享
    补充“为什么Scrum不行” (转自陈勇)
  • 原文地址:https://www.cnblogs.com/guangheli/p/11806472.html
Copyright © 2020-2023  润新知