hdu 1565 方格取数(1) dp+状态压缩
2014-12-13 14:42
274 查看
/*
用0表示没选这个数,用1表示没选
那么n<=20那么每一列的情况就可以用二进制数表示
前一列能到后一列的状态的条件是前面一列的二进制状态和后一列的二进制状态‘与’为0
而对于这些二进制状态所表示的数必须满足没有相邻的1,从而保证每一行满足条件
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 30
#define maxs 1<<20
#define inf 0x7ffffff
int dp[maxs][maxn];//dp[i][j]第i个满足条件的二进制状态在第j列的最大值
int useful[maxs];//记录满足条件的二进制数
int chess[maxn][maxn];
int n;
int judge(int i)//判断这个数是否满足条件
{
int t=i;
int cur;
int pre=t%2;
t/=2;
while(t)
{
cur=t%2;
if(cur&&pre)
return 0;
t/=2;
pre=cur;
}
return 1;
}
int count(int sum,int j)//计算sum这个二进制状态下载第j列的取值
{
int t=sum;
int pos=0;
int ans=0;
while(t)
{
if(t%2)
ans+=chess[pos][j];
pos++;
t/=2;
}
return ans;
}
int init()
{
int k=0;int i;
int upper=1<<n;
for(i=0;i<upper;i++)
if(judge(i))
{useful[k++]=i;}//存下所有满足条件的二进制状态
for(i=0;i<k;i++)
dp[i][0]=count(useful[i],0);
return k;
}
int main()
{
int i,j,k;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&chess[i][j]);
int upper=init();
for(j=1;j<n;j++)
for(i=0;i<upper;i++)
{
int temp=-inf;
for(k=0;k<upper;k++)
if((useful[k]&useful[i])==0)//前一列能转化为后一个的条件是它们的二进制状态的‘与’为0
temp=max(temp,dp[k][j-1]);
dp[i][j]=temp+count(useful[i],j);
}
int ans=-inf;
for(i=0;i<upper;i++)
ans=max(ans,dp[i][n-1]);
printf("%d\n",ans);
}
return 0;
}
用0表示没选这个数,用1表示没选
那么n<=20那么每一列的情况就可以用二进制数表示
前一列能到后一列的状态的条件是前面一列的二进制状态和后一列的二进制状态‘与’为0
而对于这些二进制状态所表示的数必须满足没有相邻的1,从而保证每一行满足条件
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 30
#define maxs 1<<20
#define inf 0x7ffffff
int dp[maxs][maxn];//dp[i][j]第i个满足条件的二进制状态在第j列的最大值
int useful[maxs];//记录满足条件的二进制数
int chess[maxn][maxn];
int n;
int judge(int i)//判断这个数是否满足条件
{
int t=i;
int cur;
int pre=t%2;
t/=2;
while(t)
{
cur=t%2;
if(cur&&pre)
return 0;
t/=2;
pre=cur;
}
return 1;
}
int count(int sum,int j)//计算sum这个二进制状态下载第j列的取值
{
int t=sum;
int pos=0;
int ans=0;
while(t)
{
if(t%2)
ans+=chess[pos][j];
pos++;
t/=2;
}
return ans;
}
int init()
{
int k=0;int i;
int upper=1<<n;
for(i=0;i<upper;i++)
if(judge(i))
{useful[k++]=i;}//存下所有满足条件的二进制状态
for(i=0;i<k;i++)
dp[i][0]=count(useful[i],0);
return k;
}
int main()
{
int i,j,k;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&chess[i][j]);
int upper=init();
for(j=1;j<n;j++)
for(i=0;i<upper;i++)
{
int temp=-inf;
for(k=0;k<upper;k++)
if((useful[k]&useful[i])==0)//前一列能转化为后一个的条件是它们的二进制状态的‘与’为0
temp=max(temp,dp[k][j-1]);
dp[i][j]=temp+count(useful[i],j);
}
int ans=-inf;
for(i=0;i<upper;i++)
ans=max(ans,dp[i][n-1]);
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- HDU 1565 方格取数(1)(状态压缩DP)
- hdu 1565 方格取数(1)(DP 状态压缩)
- hdu 1565 方格取数(1) (最小割/状态压缩+DP)
- hdu-1565(方格取数(1))---状态压缩
- hdu 1565 方格取数(1) (状态压缩DP)
- HDU 1565 方格取数(1) 状态压缩DP
- hdu 1565 方格取数(1)(状态压缩dp)
- HDU 1565 方格取数(1) (状态压缩 DP)
- hdu 1565 方格取数(1) 状态压缩dp
- Hdu 1565 方格取数(1) 状态压缩
- hdu 1565 方格取数(1) (状态压缩dp)
- Hdu-1565 方格取数(1) (状态压缩dp入门题
- 状态压缩DP——hdu 1565 方格取数1
- Hdu-1565 方格取数(1) (状态压缩dp入门题
- hdu 1565 方格取数(1) 状态压缩+dp
- HDU 1565 方格取数(1) (状态压缩DP)
- HDU1565 方格取数(1)(状态压缩dp)
- hdu 1565 方格取数(1)(状态压缩DP)
- hdu 1565 方格取数(1) 状态压缩dp
- HDU-1565 方格取数(1) 状态压缩DP