您的位置:首页 > 其它

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

2014-08-04 12:58 597 查看
题目链接:点击打开链接

本题的测试实例其实是n<=16不然用状压是过不了的 17000*17000*20 必须TLE的

#include<stdio.h>
#include<string.h>

int dp[25][20000];//存第i层 取第j种状态能得到的最大值

int num[20000];//存合法状态
int map[25][25];//存矩阵

int limit;//枚举上界

void init(int n)//初始化
{
memset(dp,0,sizeof(dp));

int i,j,sum;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&map[i][j]);
}

}

for(i=0;num[i]<limit;i++)//先初始化第0行dp[0][k]的值
{
sum=0;
for(j=0;(1<<j)<=num[i];j++)
{
if(((1<<j)&num[i])!=0)
sum+=map[0][j];
}
dp[0][i]=sum;
//   printf("dp[0][%d] %d\n",num[i],dp[0][i]);
}
//printf("limit %d",limit);
}
int main()
{
int i,j,k,n,size,sum,max;
size=0;

limit=1<<20;
for(i=0;i<limit;i++)//枚举所有合法状态  每一行内没有相邻的两个1 共17000多种
{
if((i&(i<<1))==0)
num[size++]=i;
}
while(scanf("%d",&n)!=EOF)
{
if(n==0)
{
printf("0\n");
continue;
}

limit=1<<n;
//printf("limit %d\n",limit);
init(n);

for(i=1;i<n;i++)//第0行已经初始化过 从第一行dp
{
for(j=0;num[j]<limit;j++)//遍历当前行的合法状态
{
sum=0;//存当前行所取的数字之和
max=0;// 上一层与当前行不冲突的状态的最大值
for(k=0;(1<<k)<=num[j];k++)//求当前行所取的数字之和
{
if(((1<<k)&num[j])!=0)
sum+=map[i][k];
}
// printf("sum %d\n",sum);

for(k=0;num[k]<=limit;k++)//求上一层与当前行不冲突的状态的最大值
{
if((num[k]&num[j])==0)
{
if(dp[i-1][k]>max)max=dp[i-1][k];
}
}
dp[i][j]=max+sum;
//  printf(" i j %d %d %d\n",i,num[j],dp[i][j]);
}
}

max=0;
for(i=0;i<limit;i++)
{
if(dp[n-1][i]>max)max=dp[n-1][i];
}
printf("%d\n",max);// dp到最后一层的最大值就是最终的结果了

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: