您的位置:首页 > 其它

HDU 4539 郑厂长系列故事——排兵布阵【状压dp】

2018-01-29 16:34 302 查看

郑厂长系列故事——排兵布阵

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)

Total Submission(s): 3197    Accepted Submission(s): 1126


[align=left]Problem Description[/align]
  郑厂长不是正厂长

  也不是副厂长

  他根本就不是厂长

  事实上

  他是带兵打仗的团长

  一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。

  根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。

  现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。

 

[align=left]Input[/align]
输入包含多组测试数据;

每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;

接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。

 

[align=left]Output[/align]
请为每组数据计算并输出最多能安排的士兵数量,每组数据输出一行。

 

[align=left]Sample Input[/align]


6 60 0 0 0 0 00 0 0 0 0 00 0 1 1 0 00 0 0 0 0 00 0 0 0 0 00 0 0 0 0 0

 
[align=left]Sample Output[/align]


2
因为攻击距离是2,所以开三维数组;
当两个人距离为根号二时距离记做2,即不能处在相邻对角线位置;
dp[i][j][k]记录的是第i行j状态,i-1行k状态的最大人数;

#include<bits/stdc++.h>
using namespace std;
#define mms(x) memset(x, 0, sizeof x)
const int MAX = 1 << 11;
int maps[105], dp[105][200][200], vis[MAX], linenum[MAX];
int getnum(int x)
{
int i = 0;
while(x > 0)
{
i++;
x &= (x - 1);
}
return i;
}
bool judge_place(int x)
{
return x & (x << 2);
}
bool judge_vis(int i, int j)
{
return maps[i] & vis[j];
}
bool judge_line(int i, int j)
{
return vis[i] & vis[j];
}
int main()
{
ios::sync_with_stdio(false);
int n, m;
while(cin >> n >> m)
{
mms(maps);
mms(dp);
mms(vis);
mms(linenum);
for(int i = 1; i <= n; i++)
for(int j = 1, x; j <= m; j++)
{
cin >> x;
if(!x)
maps[i] += (1 << (j - 1));
}
int ans = -MAX, num = 0;
for(int i = 0; i < (1 << m); i++)
if(!judge_place(i))
{
vis[num] = i;
linenum[num++] = getnum(i);
}
for(int i = 0; i < num; i++)
if(!judge_vis(1, i))
dp[1][i][0] = linenum[i];
for(int i = 2; i <= n; i++)
for(int j = 0; j < num; j++)
if(!judge_vis(i, j))
for(int k = 0; k < num; k++)
if(!((vis[j] & (vis[k] >> 1)) || (vis[j] & (vis[k] << 1))))
for(int l = 0; l < num; l++)
if(!judge_line(j, l))
dp[i][j][k] = max(dp[i][j][k], dp[i - 1][k][l] + linenum[j]);
for(int i = 0; i < num; i++)
for(int j = 0; j < num; j++)
ans = max(ans, dp
[i][j]);
cout << ans << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: