您的位置:首页 > 其它

HDU 1565 方格取数(1) (状态压缩)

2014-08-06 21:20 155 查看
没什么好说的,主要看代码注释,取数,某个位置能放东西,某个位置不能放等等,这类写法基本都是这样

用01串表示状态,1表示取,0表示不取,01串对应的10进制数存起来,关于位运算点击打开链接(来自百度百科),具体某个位运算有什么意义看代码注释

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


题目链接:点击打开链接

代码注释:

<strong><span style="font-size:18px;color:#ff6600;">#include<iostream>
#include<cstring>
using namespace std;
#define N 20000 //开到20000就够了 开到1<<20会超内存
int q
,dp[21]
,a[21][21];
int main()
{
int n,i,j,sum;
while(cin>>n)
{
int sum=0;
for(i=0; i<(1<<n); i++)
if((i&(i<<1))==0)  //将所有满足相邻不取的情况存起来
q[sum++]=i;
for(i=1; i<=n; i++)
for(j=0; j<n; j++)
cin>>a[i][j];
memset(dp,0,sizeof(dp));
for(i=1; i<=n; i++)
for(j=0; j<sum; j++)
{
int ans=0;
for(int p=0; p<n; p++)
if((q[j]&(1<<p))!=0)//q[j]中存的是一个01串,p从移动0位到n-1位依次左移,直到和q[j]取&不为0,即第p位数要取,且该位为1
ans+=a[i][p];
dp[i][j]=ans;
for(int k=0; k<sum; k++)
if((q[j]&q[k])==0)//如果本行和上一行不相邻,q[k]是上一行的状态
dp[i][j]=max(dp[i][j],dp[i-1][k]+ans);//状态转移方程,i-1可以理解为这个1是留给本行的,ans就是本行的和

}
int ans=-1;
for(i=0; i<sum; i++)//dp[i][j]数组中存的就是前i行,各种状态下(取某个数或不去某个数)的取得数的和,在最后一行dp中找出最大即可
ans=max(dp
[i],ans);
cout<<ans<<endl;
}
}</span></strong>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: