zoukankan      html  css  js  c++  java
  • POJ1038 Bugs Integrated, Inc 状压DP+优化

    (1) 最简单的4^10*N的枚举(理论上20%

    (2) 优化优化200^3*N的枚举(理论上至少50%

    (3) Dfs优化状压dp O(我不知道,反正过不了,需要再优化)(理论上80%

    (4) 再剩下的,卡常数+卡常数+一个小优化(自己想吧,有可能被卡一个点)

    (5) 如果还没有过,dfs中可能有重复的状态,用链式前向星优化一下,就差不多了

    (6) 以上属于乱搞,正解在下面

    (7) O(3^10*N),我们知道,设,我们更新第i行的状态,那么如果第i-1行的第j个位置不能被选取,则第i-2行的第j个位置同样不可以被选取,那么4^N状态转化为3^N,理论时间复杂度可能会超时(这个大概是60-70%的样子),所以需要用到Dfs优化(这个大概70-100%,有的人就能,反正我没有),之后同样,用链式前向星优化一下,就可以过了,当然,如果你还不满足于这个时间复杂度的话,还可以继续优化,这个就不写在这里了。

    乱搞程序

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <queue>
    using namespace std;
    #define N 155
    #define M 205
    #define max(a,b) ((a)<(b)?(b):(a))
    int f[3][M][M],cur[N],n,m,K,can[M],p[1<<15],cnt2,head[M][M];
    int to[M*M*30],to2[M*M*30],to3[M*M*30],cnt[M*M*30],next[M*M*30];
    int a,b,ans,cnt4;
    void dfs(int f1,int f2,int step,int f3,int cnt1)
    {
    	if(to[cnt4]!=f1||to3[cnt4]!=f2)
    	{
    		to[++cnt4]=f1;
    		to2[cnt4]=f3;
    		to3[cnt4]=f2;
    		cnt[cnt4]=cnt1;
    		next[cnt4]=head[a][b];
    		head[a][b]=cnt4;
    	}
    	if(step>=m)return ;
    	if(step<m-1&&!(f1&(3<<step))&&!(f2&(3<<step)))
    	{
    		dfs(f1|(3<<step),f2|(3<<step),step+2,f3|(3<<step),cnt1+1);
    	}
    	if(step<m-2&&!(f1&(7<<(step))))
    	{
    		dfs(f1|(7<<step),f2,step+3,f3|(7<<step),cnt1+1);
    	}
    	if(step<m-2&&!(f1&(7<<step))&&!(f2&(7<<step)))
    	{
    		dfs(f1|(7<<step),f2|(7<<step),step+3,f3,cnt1+1);
    	}
    	dfs(f1,f2,step+1,f3,cnt1);
    	return ;
    }
    void init()
    {
    	memset(cur,0,sizeof(cur));
    	memset(head,0,sizeof(head));
    	cnt4=0;
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		init();
    		scanf("%d%d%d",&n,&m,&K);
    		int mask=(1<<m)-1;
    		for(int i=1;i<=K;i++)
    		{
    			int x,y;
    			scanf("%d%d",&x,&y);
    			cur[x]|=(1<<(y-1));
    		}
    		cur[0]=cur[n+1]=mask;
    		ans=0;cnt2=0;
    		for(int j=0;j<=mask;j++)
    		{
    			int s=j;
    			if(((s&3)==1)||(s!=0&&((((~s))&((~s)<<2))&&(((((~s))&((((~s)))<<2))>>1)&s))))continue;
    			can[++cnt2]=j;
    			p[j]=cnt2;
    		}
    		for(int i=1;i<=cnt2;i++)
    		{
    			for(int j=1;j<=cnt2;j++)
    			{
    				if((can[i]&can[j])!=can[i])continue;
    				a=i,b=j;
    				dfs(can[i],can[j],0,0,0);
    			}
    		}
    		memset(f[1],0,sizeof(f[1]));
    		for(int i=1;i<n;i++)
    		{
    			memset(f[(i+1)&1],0,sizeof(f[(i+1)&1]));
    			for(int j=1;j<=cnt2;j++)
    			{
    				if(can[j]&cur[i])continue;
    				for(int k=j;k<=cnt2;k++)
    				{
    					if((can[k]&cur[i-1]))continue;
    					if((can[k]&can[j])!=can[j])continue;
    					for(int l=head[j][k];l;l=next[l])
    					{
    						if((to[l]&cur[i])||(to3[l]&cur[i-1])||(to2[l]&cur[i+1]))continue;
    						f[(i^1)&1][p[to2[l]]][p[to[l]|to2[l]]]=max(f[(i^1)&1][p[to2[l]]][p[to[l]|to2[l]]],f[i&1][j][k]+cnt[l]);
    					}
    					if(i==1)break;
    				}
    			}
    			for(int j=1;j<=cnt2;j++)
    			{
    				for(int k=1;k<=cnt2;k++)
    				{
    					ans=max(ans,f[(i+1)&1][j][k]);
    				}
    			}
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    转:imageNamed和dataWithContentsOfFile的区别
    [内存管理实践 之 1]在返回按钮中,释放内存
    转:当程序崩溃的时候怎么办 Part2
    iOS 内存管理,我们需要一套切实可行的实践指导书,而不是理论指导书
    转 iOS程序中调用系统自带应用(短信,邮件,浏览器,地图,appstore,拨打电话)
    iOS笔记:内存管理
    转:【图文教程】创建Xcode自定义模板
    判断两个数的大小,返回其中的大者/小者
    iOS全局变量与属性的内存管理
    UIImage 详解
  • 原文地址:https://www.cnblogs.com/Winniechen/p/8890819.html
Copyright © 2011-2022 走看看