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

来源:互联网 发布:人工智能发展的看法 编辑:程序博客网 时间:2024/05/20 04:28

做了很久的一道题。
做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;}
0 0
原创粉丝点击