[POJ1185] [NOI2001] 炮兵阵地 [状态压缩][dp]

本文深入探讨了状压DP这一高效算法的核心概念与实现细节,通过具体实例讲解如何运用状压DP解决复杂问题,包括状态定义、转移方程及优化技巧。适合有一定算法基础的读者进一步提升解题能力。

[ L i n k \frak{Link} Link]

状压就两个字

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<queue>
#include<cctype>
using namespace std;
void out(int x) { while(x) { cout<<(x&1); x>>=1;} }
bool c=0;
char ch;
int L[62]={},B[62]={},A[102]={};
long long F[2][62][62]={},Ans=0,N,M,Lim;
void pre(int step,int state,int cnt,int cooldown)
{
	if(step==M)
	{
		L[++L[0]]=state;
		B[L[0]]=cnt;
		return;
	}
	if(!cooldown)pre(step+1,state|(1<<step),cnt+1,2);
	pre(step+1,state,cnt,max(cooldown-1,0));
}
int main()
{
	scanf("%d%d",&N,&M); Lim=(1<<M)-1;
	pre(0,0,0,0);
	for(int i=1;i<=N;++i)
	{
		for(int j=0;j<M;++j)
		{
			scanf(" %c",&ch);
			if(ch=='H')A[i]|=1<<j;
		}
	}
	for(int i=1;i<=N;++i)
	{
		c=i&1;
		memset(F[c],0,sizeof(F[c]));
		for(int j=1;j<=L[0];++j)
		{
			if(A[i]&L[j])continue;
			for(int k=0;k<=L[0];++k)
			{
				for(int g=0;g<=L[0];++g)
				{
					if((L[k]&L[g])||(L[j]&L[k])||(L[j]&L[g]))continue;
					F[c][j][k]=max(F[c][j][k],F[!c][k][g]+B[j]);
				}
			}
		}
	}
	for(int i=1;i<=L[0];++i)
	{
		for(int j=1;j<=L[0];++j)
		{
			Ans=max(Ans,F[c][i][j]);
		}
	}
	printf("%lld",Ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值