您的位置:首页 > 其它

poj -1185 炮兵阵地 (经典状压dp)

2015-08-10 11:35 309 查看
http://poj.org/problem?id=1185

参考博客:http://poj.org/problem?id=1185

大神博客已经讲的很清楚了,注意存状态的时候是从1开始的,所以初始化的时候也是dp[1][1][state],从0开始的话,状态就是dp[1][0][state]了.

dp[i][j][k]表示第i行状态为k第i-1行状态为j时的方案数.

dp[i][j][k]=max(dp[i][j][k],dp[i-1][t][j]+num[k]); (num[k]为k状态中1的个数)

边界条件:dp[1][1][i]=num[i],状态i可以满足第一行的条件。

还有就是为什么每一行最多只有60种状态,poj题目讨论里面有人给出了枚举的代码。

#include <iostream>
using namespace std;
bool isok( int c ) {
return !(c&(c<<1)||c&(c<<2));//同一行中不能有相邻的1距离小于3
}
int main() {
int count=0;
for( int i=0; i<1024; i++ )
count += isok(i);
cout<<count<<endl;
return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
//#include <map>
#include <queue>
#include <deque>
//#pragma comment(linker, "/STACK:102400000,102400000")
#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define ll long long
#define INF 0x7f7f7f7f
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)

#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("a.txt", "r", stdin)
#define Write() freopen("b.txt", "w", stdout);
#define maxn 110
#define maxv 5010
#define mod 1000000000
using namespace std;
int n,m;
char map[110][20],num[110],top;
int stk[70],cur[110];
int dp[110][70][70];

inline bool ok(int x) //判断该状态是否合法,即同一行不存在相邻1之间的距离小于3的
{
if(x&(x<<1)||x&(x<<2)) return 0;
return 1;
}
inline void jnite() //找到所有可能合法的状态
{
top=0;
int total=1<<m;
for(int i=0;i<total;i++)
if(ok(i)) stk[++top]=i;
}

inline bool fit(int x,int k) //判断状态x是否与第k行匹配
{
if(cur[k]&x) return 0;
return 1;
}
inline int jcount(int x) //计算一个整型数x的二进制中1的个数(用于初始化)
{
int cnt=0;
while(x)
{
cnt++;
x&=(x-1); //很精炼,每次都会与掉一个1
}
return cnt;
}
int main()
{
//Read();
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
jnite();
for(int i=1;i<=n;i++) scanf("%s",map[i]+1);
for(int i=1;i<=n;i++)
{
cur[i]=0;
for(int j=1;j<=m;j++)
{
if(map[i][j]=='H') cur[i]+=(1<<(j-1));
}
//printf("%d\n",cur[i]);
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=top;i++) //初始化第一行
{
num[i]=jcount(stk[i]);
//printf("%d\n",num[i]);
if(fit(stk[i],1)) dp[1][1][i]=num[i];
}
for(int i=2;i<=n;i++) {
for(int t=1;t<=top;t++) {
if(!fit(stk[t],i)) continue;//第i行是否冲突
for(int j=1;j<=top;j++) {
if(stk[t]&stk[j]) continue;//第i行和第i-2行是否冲突
for(int k=1;k<=top;k++) {
if(stk[t]&stk[k]) continue;//第i行和第i-1行是否冲突
dp[i][k][t]=max(dp[i][k][t],dp[i-1][j][k]+num[t]);
//  printf("%d\n",dp[i][k][t]);
}
}
}
}
int ans=0; //得到最大值
for(int i=1;i<=top;i++)
for(int j=1;j<=top;j++)
ans=max(ans,dp
[i][j]);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: