zoukankan      html  css  js  c++  java
  • P2157 [SDOI2009]学校食堂 状压DP

    题意:

    有点复杂,自行浏览吧 题目链接

    分析:

    我们发现DP转移时需要记录以下几个信息:

    打饭队列的队首是谁,上一个打饭的是谁,队列前(b[i])个人的状态

    然后我们根据这些信息设立DP状态,记(f[i][j][k])表示该第(i)个人打饭(等价于前(i-1)个人已经买完饭)此时队列前7个人的状态是(j),上一个打饭的人是(i+k)。由于打饭的人在(i)的前后都可以,所以(k)的范围就是([-8,8]),加上偏移量就是([0,16])

    接下来我们考虑转移,分为两种情况:

    1. (i)个人已经买完饭了,也就是说直接将状态转移到(i+1)就可以了
    f[i+1][j>>1][k-1]=min(f[i+1][j>>1][k-1],f[i][j][k]);
    
    1. (i)个人还没有买饭,那就在所有人都能忍受的范围内枚举买饭的人是谁
    f[i][j|(1<<l)][l]=min(f[i][j|(1<<l)][l],f[i][j][k]+(t[i+k]^t[i+l]));
    

    状态初始化为(f[1][0][7])表示该第(1)个人买饭,此时身后所有人都没有买完,上一个买的人是第(7-8)个,最后统计枚举(i)然后取(f[n+1][0][i])的最小值

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
    	const int maxn = 1005;
    	int f[maxn][256][20],b[maxn],t[maxn];
    	int T,n;
    
    	void work()
    	{
    		scanf("%d",&T);
    		while(T--)
    		{
    			memset(f,0x3f,sizeof(f));
    			scanf("%d",&n);
    			for(int i=1;i<=n;i++) scanf("%d%d",&t[i],&b[i]);
    			f[1][0][7]=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+8]!=0x3f3f3f)
    						{
    							if(j&1) f[i+1][j>>1][k+7]=min(f[i+1][j>>1][k+7],f[i][j][k+8]);
    							else
    							{
    								int lim=0x3f3f3f;
    								for(int l=0;l<=7;l++)
    								{
    									if(!((j>>l)&1))
    									{
    										if(i+l>lim) break;
    										lim=min(lim,i+l+b[i+l]);
    										f[i][j|(1<<l)][l+8]=min(f[i][j|(1<<l)][l+8],f[i][j][k+8]+(i+k?t[i+k]^t[i+l]:0));
    									}
    								}
    							}
    						}
    					}
    				}
    			}
    			int ans=0x3f3f3f;
    			for(int i=0;i<=8;i++) ans=min(ans,f[n+1][0][i]);
    			printf("%d
    ",ans);
    		}
    	
    	}
    
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
    
  • 相关阅读:
    segmentation fault(core dumped)
    (LIS LCS 例题)Max Sum Advanced Fruits Super Jumping! Jumping! Jumping!
    几种数学公式(环排列 母函数 唯一分解定理 卡特兰数 默慈金数 贝尔数 那罗延数)
    map set 详解
    算法录 之 二分和三分
    LIS 最长上升子序列 LCS 最长公共子序列 模板
    JAVA 大数据 例题
    Java 实现大数算法
    7 21 第一次团队赛——————写给队友
    离散化+unique()+二分查找
  • 原文地址:https://www.cnblogs.com/youth518/p/13848950.html
Copyright © 2011-2022 走看看