hdu 4539 郑厂长系列故事——排兵布阵
郑厂长系列故事——排兵布阵
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1294 Accepted Submission(s): 470
Problem Description
郑厂长不是正厂长
也不是副厂长
他根本就不是厂长
事实上
他是带兵打仗的团长
一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。
也不是副厂长
他根本就不是厂长
事实上
他是带兵打仗的团长
一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。
Input
输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。
每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。
Output
请为每组数据计算并输出最多能安排的士兵数量,每组数据输出一行。
Sample Input
6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Sample Output
2
Source
// ans[] 里面存的是 m 个 1 能达到所有的状态
//如果 m == 2 , 则可以达到 00 01 10 11 既0,1,2,3
// dp[i][j][k] 表示 计算到 第 i 行 状态是 ans[j] , 上一行 状态是 ans[k] ;
// 然后枚举上一行的所有状态 和上一行判断是否有冲突 ,
//可以把上一行的状态 向左和向右移一位(二进制),判断是否有同 1
// 和上一行的上一行只要判断是否同为一就好了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<algorithm>
#define maxn 110
#define INF 100
#define LL long long
#define mod 1000000007
using namespace std ;
int len , f[14],m ,num[200],n;
int ans[200] , dp[110][172][172] ;
bool vi[1025] , map1[110][11] ;
void dfs( int cur , int sum , int a , int mm )
{
if(cur > m )
{
num[len] = mm ;
ans[len++] = sum ;
return ;
}
dfs(cur+1,sum,a+1,mm) ;
if(cur >= 3 && f[cur-2] == 1 ) return ;
f[cur] = 1 ;
dfs(cur+1,sum+(1<<a),a+1,mm+1) ;
f[cur] = 0 ;
}
int get( int cur )//返回cur 行可以达到最大的状态值是多少
{
int ans = 0, i;
for( i = 0 ; i < m ;i++ )
{
if(map1[cur][i+1]) ans += (1<<i) ;
}
return ans ;
}
bool check1( int b , int a )
{
int a1 , a2 ;
a1 = a<<1 ;a2 = a>>1 ;
if((a1&b)||(a2&b)) return false ;
return true ;
}
bool check2( int a , int b )
{
if(a&b) return false ;
return true ;
}
int main()
{
int i , j ,aa , bb , k , v ;
int Max ;
//freopen("in.txt","r",stdin) ;
while( scanf("%d%d" , &n , &m ) != EOF )
{
len = 1 ;
memset(f,0,sizeof(f)) ;
//枚举所有状态
dfs(1,0,0,0) ;
sort(ans+1,ans+len) ;
// for( i = 1 ; i < len ;i++)cout << ans[i] << " " ;
for( i = 1 ; i <= n ;i++ )
for( j = 1 ; j <= m ;j++ )
{
scanf("%d",&aa) ;
if(aa==1)map1[i][j] = 1 ;
else map1[i][j] = 0 ;
}
bb = get(1) ;
Max = 0 ;
memset(dp,0,sizeof(dp)) ;
for( i = 1 ; i < len ;i++ )if((ans[i]|bb) <= bb )//如果 ans[i] 可达, 既 bb 为一的 ans[i] 可以为 1 ,为0 的 ans[i] 只可以为 0
{
for( j = 1 ; j < len ;j++ )
dp[1][i][j] = num[i] ;
}
for( i = 2 ; i <= n ;i++ )
for( j = 1 ; j < len ;j++ )
{
bb = get(i) ;
if((bb|ans[j]) > bb )continue ;
for( k = 1 ; k < len ;k++ )if(check1(ans[j],ans[k])||bb==0)
for( v = 1 ; v < len ;v++ )if(check2(ans[j],ans[v])||bb==0){
dp[i][j][k] = max(dp[i][j][k],dp[i-1][k][v]+num[j]) ;
}
}
for( i = 1 ; i < len ;i++ )
for( j = 1 ; j < len ;j++ )
Max = max(Max,dp[n][i][j]) ;
cout << Max << endl;
}
}

浙公网安备 33010602011771号