状态压缩dp poj1185

前天把状态压缩彻底弄明白啦,哈哈!昨天和今天写了两道状态压缩题,高兴啊!今天开始做树形dp,感觉和前天刚解除状态压缩一样,嘿嘿,都是会解决的啦!这两天校运会,感觉比上课都累啊!而且只有晚上看题,保持一晚上一道题,收获不小啊!

这道题是典型的状态压缩dp,不过注意一下优化:

空间优化:对于那些本来就不符合的状态就不要记录了,不然会超内存的!

时间优化:对于上面两行组成的状态不成立的直接进行下一个循环,不用浪费时间!

下面是我的代码:

#include<iostream>
#include<cstdio>
#include<string> 
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<climits>
using namespace std; 
#define rep(i,n) for(i=0; i<(n); i++)
#define reph(i,n,m) for(i=(n); i<=(m); i++)//正循环的
#define repd(i,n,m) for(i=(n); i>=(m); i--) //负循环的 
#define max(a,b) (a)>(b)?(a):(b)
#define fab(a) (a)>0?(a):0-(a)
#define ll long long
#define arc(a) (a)*(a)
#define inf 100000000   //最大值的
#define exp 0.0000001     //浮点型的
#define N    10 //记录开的数组
int f[105];
int dp[105][100][100];
int a[105];//记录满足最基本题意的解的
bool fun(int a,int m)
{
   int i=0;
   int x=-(m+1);
   while(a!=0)
   {
     if(a%2==1)
     { 
        if(i-x<(m+1))
         return true; //代表不满足题意的 
        x=i;
       
     }
     i++;
	 a=a>>1;
   }     
   return false;
} 
bool panduan(int a,int b,int c)
{
     if((a&c)!=0 || (b& c)!=0)
      return false;//就是有相同的点的  
     return true; 
}

int find(int a)
{
    int sum=0;
    while(a!=0)
    {
        if(a%2==1)
         sum++;
         a=a>>1;
    }
    return sum;
}
int main()
{
	int n,m,i,j,k,l,r;
	char s[15];
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		reph(i,1,n)
		{
			scanf("%s",s);
			f[i]=0;
			reph(j,0,m-1)
			{
				f[i]=f[i]<<1;
				if(s[j]=='P')
					f[i]+=1;
			}
		}
		memset(dp,0,sizeof(dp));
        r=1<<m;
		j=0;//记录满足题意的解的
		reph(i,0,r-1)
			if(!fun(i,2))//满足两个站点之间的间隔为2的,任何两个炮兵部队不能相互攻击的
              a[j++]=i;//记录的
		r=j;//从0到r-1的
		reph(i,1,n)
		{
            reph(j,0,r-1)
			{
				if((a[j]&f[i])!=a[j])//不存在a【j】这种情况的
					continue;
                reph(k,0,r-1)
					reph(l,0,r-1)
				{ 
					if((a[k] & a[l])!=0)//k和l这种情况就不存在的
						continue;
					if(panduan(a[k],a[l],a[j]))
						dp[i][l][j]=max(dp[i][l][j],dp[i-1][k][l]+find(a[j]));
				}
			}
		}
		int Max=0;
		reph(i,0,r-1)
			reph(j,0,r-1)
			  Max=max(Max,dp[n][i][j]);
		printf("%d\n",Max);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡定的小Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值