您的位置:首页 > 其它

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

2015-10-15 14:17 363 查看
做了很久的一道题。

做dp题要先写出子问题。

做dp题要先写出子问题。

做dp题要先写出子问题。

dp[i][j]代表到第i行第j种情况,能取得的最大的数。

所以dp[i][j]=max(dp[i-1][k]+sum,dp[i][j]);

这里k&j!=1。sum为改行的值。

定义一个dp[20][1<<20]的数组mle,可以定义一个dp【2】【1<<20】的滚动数组。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int dp[2][1<<20];
int s[20000];
int n;
int map[25][25];
int k=0;
void solve(int x,int y)
{
if(x>=n-1)
return ;
int p=y&1;
for(int i=1;i<k;i++)
{
if(s[i]>=(1<<n))
break;
for(int j=1;j<k;j++)
{
if(s[j]>=(1<<n))
break;
if(s[j]&s[i])
continue;
int sum=0;
for(int kk=0;kk<n;kk++)
{
if(s[j]&(1<<kk))
sum+=map[y][kk];
}
dp[p][s[j]]=max(sum+dp[1-p][s[i]],dp[p][s[j]]);
}
}
solve(x+1,y+1);
return ;
}
int main()
{
for(int i=0;i<(1<<20);i++)
if(!(i&(i<<1)))
s[k++]=i;
while(cin>>n)
{
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&map[i][j]);
int end=1<<n;
for(int i=1;i<k;i++)
{
int sum=0;
if(s[i]>=end)
break;
for(int j=0;j<n;j++)
{
if(s[i]&(1<<j))
sum+=map[0][j];
}
dp[0][s[i]]=sum;
}
solve(0,1);
int maxv=0;
for(int i=1;i<end;i++)
{
int d=(n-1)&1;
maxv=max(dp[d][i],maxv);
}
cout<<maxv<<endl;
}
return 0;
}


不过这份代码耗时比较大,应该是有可以优化的地方。

优化后的代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int dp[2][1<<20];
int s[20000];
int n;
int map[25][25];
int main()
{
int lon=0;
for(int i=0;i<(1<<20);i++)
if(!(i&(i<<1)))
s[lon++]=i;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&map[i][j]);
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
int p=i&1;
for(int k=1;k<lon;k++)
{
if(s[k]>=(1<<n))
break;
int sum=0;
for(int j=0;j<n;j++)
if(s[k]&(1<<j))
sum+=map[i][j];
int maxv=0;
for(int j=1;j<lon;j++)
{
if(s[j]>=(1<<n))
break;
if(s[j]&s[k])
continue;
maxv=max(dp[1-p][s[j]],maxv);
/*cout<<maxv<<endl;*/
}
dp[p][s[k]]=maxv+sum;
}
}
int maxn=0;
int d=(n-1)&1;
for(int i=0;i<lon;i++)
if(s[i]<(1<<n))
maxn=max(maxn,dp[d][s[i]]);
cout<<maxn<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp 状态压缩