HDU4539 郑厂长系列故事——排兵布阵【状压DP】
2017-08-14 15:51
169 查看
HDU4539链接
题意: 一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。
输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。
分析:经典状压DP,把每一行安排士兵的状态压缩(利用二进制),然后状态转移方程也比较好写。(如果第一次做这个类型建议先做POJ1185)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long LL;
const int N=1<<15;
int n2,n,m;
int dp[105][188][188],w[353],num[353],a[111],b[15];
int dfs(int cnt,int x) //利用DFS深搜放士兵的位置,并记录
{
for(int i=x;i<=m;i++)
{
if(cnt==1||(!b[i]&&!b[i-2]))
{
b[i]=1;
for(int j=1;j<=m;j++)
{
if(b[j])
{w[n2]|=(1<<(j-1));
//cout<<j-1<<" ";
}
}
// cout<<endl;
num[n2]=cnt;
n2++;
dfs(cnt+1,i+1);
b[i]=0;
}
}
}
int main()
{
int x;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(w,0,sizeof(w));
n2=1;
memset(b,0,sizeof(b));
dfs(1,1);
//cout<<n2<<endl;
for(int i=1;i<=n;i++)
{
a[i]=0;
for(int j=0;j<m;j++)
{
scanf("%d",&x);
if(x)
a[i]|=(1<<j);
}
}
memset(dp,-1,sizeof(dp));
for(int i=0;i<n2;i++)
{
if((a[1]|w[i])==a[1])
dp[1][0][i]=num[i];
}
for(int i=1;i<n;i++)
{
for(int j=0;j<n2;j++)
{
for(int k=0;k<n2;k++)
{
if(dp[i][j][k]==-1)continue;
for(int l=0;l<n2;l++)
{
if((a[i+1]|w[l])!=a[i+1])continue;
if(w[j]&w[l]||(w[k]>>1)&w[l]||(w[k]<<1)&w[l])continue;
dp[i+1][k][l]=max(dp[i+1][k][l],dp[i][j][k]+num[l]);
}
}
}
}
int ans=0;
for(int i=0;i<n2;i++)
{
for(int j=0;j<n2;j++)
{
ans=max(dp
[i][j],ans);
}
}
printf("%d\n",ans);
}
return 0;
}
题意: 一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。
输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。
分析:经典状压DP,把每一行安排士兵的状态压缩(利用二进制),然后状态转移方程也比较好写。(如果第一次做这个类型建议先做POJ1185)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long LL;
const int N=1<<15;
int n2,n,m;
int dp[105][188][188],w[353],num[353],a[111],b[15];
int dfs(int cnt,int x) //利用DFS深搜放士兵的位置,并记录
{
for(int i=x;i<=m;i++)
{
if(cnt==1||(!b[i]&&!b[i-2]))
{
b[i]=1;
for(int j=1;j<=m;j++)
{
if(b[j])
{w[n2]|=(1<<(j-1));
//cout<<j-1<<" ";
}
}
// cout<<endl;
num[n2]=cnt;
n2++;
dfs(cnt+1,i+1);
b[i]=0;
}
}
}
int main()
{
int x;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(w,0,sizeof(w));
n2=1;
memset(b,0,sizeof(b));
dfs(1,1);
//cout<<n2<<endl;
for(int i=1;i<=n;i++)
{
a[i]=0;
for(int j=0;j<m;j++)
{
scanf("%d",&x);
if(x)
a[i]|=(1<<j);
}
}
memset(dp,-1,sizeof(dp));
for(int i=0;i<n2;i++)
{
if((a[1]|w[i])==a[1])
dp[1][0][i]=num[i];
}
for(int i=1;i<n;i++)
{
for(int j=0;j<n2;j++)
{
for(int k=0;k<n2;k++)
{
if(dp[i][j][k]==-1)continue;
for(int l=0;l<n2;l++)
{
if((a[i+1]|w[l])!=a[i+1])continue;
if(w[j]&w[l]||(w[k]>>1)&w[l]||(w[k]<<1)&w[l])continue;
dp[i+1][k][l]=max(dp[i+1][k][l],dp[i][j][k]+num[l]);
}
}
}
}
int ans=0;
for(int i=0;i<n2;i++)
{
for(int j=0;j<n2;j++)
{
ans=max(dp
[i][j],ans);
}
}
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- hdoj4539郑厂长系列故事——排兵布阵【状压dp】
- hdu4539 郑厂长系列故事——排兵布阵 + POJ1158 炮兵阵地
- HDU 4539 郑厂长系列故事——排兵布阵 状压dp
- HDU 4539 郑厂长系列故事——排兵布阵【状压dp】
- [状压dp]HDOJ4539 郑厂长系列故事——排兵布阵
- 【DP】 HDU 4539 郑厂长系列故事——排兵布阵 状压
- hdu4539 郑厂长系列故事——排兵布阵(状压dp)
- [2013腾讯马拉松复赛第二场] HDU 4539 郑厂长系列故事——排兵布阵
- hdu 4539 郑厂长系列故事——排兵布阵 状态压缩dp
- hdu 4539 郑厂长系列故事——排兵布阵
- hdu 4539 郑厂长系列故事——排兵布阵 插头dp
- HDU-4539 郑厂长系列故事——排兵布阵 状态压缩DP Or 最大团
- hdu_4539_郑厂长系列故事——排兵布阵(状压DP|最大团)
- hdu 4539 郑厂长系列故事——排兵布阵
- 【状压dp】hdu 4539 郑厂长系列故事——排兵布阵
- hdu_4539_郑厂长系列故事——排兵布阵(状压DP|最大团)
- (待解决) hdu HDU4539 郑厂长系列故事——排兵布阵 (状态压缩dp~)
- hdu 4539 郑厂长系列故事——排兵布阵
- HDU 4539 郑厂长系列故事——排兵布阵 (状态压缩DP)
- hdu 4539 郑厂长系列故事——排兵布阵