您的位置:首页 > 其它

HDU 1565 方格取数(1) (状压DP)

2016-08-18 16:20 323 查看
方格取数(1)

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

Total Submission(s): 8141 Accepted Submission(s): 3073

Problem Description

给你一个n*n的格子的棋盘,每个格子里面有一个非负数。

从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。

Input

包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)

Output

对于每个测试实例,输出可能取得的最大的和

Sample Input

3

75 15 21

75 15 28

34 70 5

Sample Output

188

Author

ailyanlu

Source

Happy 2007

Recommend

8600 | We have carefully selected several similar problems for you: 1569 1532 3338 1533 1733

状压DP,首先用dfs去生成当前行所有的状态,now_status存储的是二进制的所有方案,now_sum存储的是对应每种方案(当前行的和)。pre_status存的是前一行的方案,因为当前行方案的选择和前一行有关,pre_sum存储的则是前面所有行 所有可行方案的和。

#include "cstring"
#include "cstdio"
#include "iostream"
#include "string.h"
#include "algorithm"
#include "cmath"
using namespace std;
int mmap[25][25];
int n;
int now_status[20000],now_sum[20000],nowid,preid,dp[20000],pre_status[20000],pre_sum[20000];
void dfs(int row,int column,int status,int sum)
{
if(column>=n)
{
now_status[++nowid]=status;
now_sum[nowid]=sum;
return;
}
dfs(row,column+2,status|1<<column,sum+mmap[row][column]);
dfs(row,column+1,status,sum);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(mmap,0,sizeof(mmap));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&mmap[i][j]);
memset(pre_status,0,sizeof(pre_status));
memset(now_status,0,sizeof(now_status));
memset(now_sum,0,sizeof(now_sum));
memset(pre_sum,0,sizeof(pre_sum));
memset(dp,0,sizeof(dp));
preid=0;
for(int k=0;k<n;k++)
{
nowid=-1;
dfs(k,0,0,0);
memset(dp,0,sizeof(dp));
for(int i=0;i<=nowid;i++)
{
for(int j=0;j<=preid;j++)
{
if(now_status[i]&pre_status[j])continue;
dp[i]=max(dp[i],pre_sum[j]+now_sum[i]);
}
}
for(int i=0;i<=nowid;i++)
{
pre_sum[i]=dp[i];
pre_status[i]=now_status[i];
}
preid=nowid;
}
int ans=0;
for(int i=0;i<=nowid;i++)
ans=max(ans,dp[i]);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: