您的位置:首页 > 其它

[2013腾讯马拉松复赛第二场] HDU 4539 郑厂长系列故事——排兵布阵

2013-03-30 22:10 447 查看
以后做比赛前一定补好睡眠,没有精神A不动题目……,最后一题的题意到2H才发现看错了,原来是要求曼哈顿距离等于2的而不是小于等于2的……,调了半天样例都输出1……。最后只AC了2题,第一个和最后一个,第二个怎么想怎么是爆搜,是不是爆搜?

最后一题排兵布阵是比较经典的状压DP,看群里还有用点独立集做的,还有用插头DP做的?ORZ。

做法跟POJ 1185炮兵阵地,这道经典状压DP神似,连题目都神似。所以具体转移方程也基本一样,需要枚举前两行的状态。具体细节不明白的可以先去搜poj 1185的解题报告。

题目虽然给的时间很多,但是比赛怕超时就先预处理了所有当前行可行的状态。判断当前行k,和k-2行是否兼容跟炮兵阵地的处理方式一样,直接相与。处理k跟k-1行略有不同,是把k-1行的状态搓一个位(其实就是乘2,除2)相与,看这两个结果有没有不等于0的。其他都跟炮兵一样。

View Code

#include <set>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <vector>
#include <bitset>
#include <cstdio>
#include <string>
#include <numeric>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
#define Exp 1e-8
#define inf 0x7fffffff
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#define maxn 200
int n,m,top;
int map[105][12],con[maxn][maxn],con2[maxn][maxn];
int state[maxn][2],vm[105],dp[105][maxn][maxn];
int max(int a,int b)
{
if(a>b)return a;
return b;
}
void prt(int i)
{
int t=i;while(t)printf("%d",t%2),t>>=1;puts("");
}
bool check(int a,int b)//判断当前行的状态能否放入地图中
{
if(((~b)&a))return false;
return true;
}
void init()//预处理一行能够放士兵的状态
{
int i,j;
memset(state,0,sizeof(state));
top=0;
for(i=0;i<(1<<10)-1;++i)
{
if((i&(i<<2)))continue;
state[top][0]=i;//0存放状态,1统计个数
for(j=i;j;j-=j&(-j))state[top][1]++;
++top;//prt(state[top-1][0]);
}
for(i=0;i<top;++i)for(j=0;j<top;++j)//con[i][j]表示当前行跟上一行状态为i,j是否能共存
con[i][j]=!(state[i][0]&state[j][0]);
for(i=0;i<top;++i)for(j=0;j<top;++j)//con[i][j]表示当前行跟上二行状态为i,j是否能共存
{
int t1=state[i][0]&(state[j][0]<<1);
int t2=state[i][0]&(state[j][0]>>1);
con2[i][j]=!(t1|t2);
}
}
int main()
{
//read;
init();
int i,j,k,s;
while(~scanf("%d%d",&n,&m))
{
memset(vm,0,sizeof(vm));
memset(map,0,sizeof(map));
memset(dp,0,sizeof(dp));
for(i=0;i<n;++i)
{
for(j=0;j<m;++j)
{
scanf("%d",&map[i][j]);
vm[i]=(vm[i]+map[i][j])<<1;
}
vm[i]>>=1;//地图信息状态压缩
}
for(i=0;i<top;++i)
{
if(check(state[i][0],vm[0])==0)continue;
for(j=0;j<top;j++)dp[0][i][j]=state[i][1];
}
for(i=0;i<top;++i)
{
if(check(state[i][0],vm[1])==0)continue;
for(j=0;j<top;j++)
{
if(check(state[j][0],vm[0])==0)continue;
if(con2[i][j]==0)continue;
dp[1][i][j]=max(dp[1][i][j],dp[0][j][0]+state[i][1]);
}
}
for(s=2;s<n;++s)
for(i=0;i<top;++i)
{
if(check(state[i][0],vm[s])==0)continue;
for(j=0;j<top;++j)
{
if(check(state[j][0],vm[s-1])==0)continue;
if(con2[i][j]==0)continue;
for(k=0;k<top;++k)
{
if(check(state[k][0],vm[s-2])==0)continue;
if(con2[j][k]==0||con[i][k]==0)continue;
dp[s][i][j]=max(dp[s][i][j],state[i][1]+dp[s-1][j][k]);
}
}
}
int ans=0;
for(i=0;i<top;++i)for(j=0;j<top;++j)ans=max(ans,dp[n-1][i][j]) ;
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐