HDU 1565 方格取数(1) ——插头DP

【题目分析】

    其实直接状压就可以了。

    但是有点闲,又写了一个可读性极差,智商低下,很(gou)好(pi)的代码

    

【代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
int dp[2][1<<21],n,a[20][20];
void print(int x)
{F(i,0,n)printf("%d",(x>>i)&1);}
int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        if (!n){printf("0
");continue;}
        F(i,0,n-1) F(j,0,n-1) scanf("%d",&a[i][j]);
        int now=1,pre=0;
        memset(dp[now],0,sizeof dp[now]);
        F(i,0,n-1)
            F(j,0,n-1)
            {
                now^=1;pre^=1;
                memset(dp[now],0,sizeof dp[now]);
                F(s,0,(1<<(n+1))-1)
                {
//                    print(s); printf(" is %d to",dp[pre][s]);
                    if ((!(s&(1<<j)))&&(!(s&(1<<(j+1))))) dp[now][s|(1<<j)|(1<<(j+1))]=max(dp[now][s|(1<<(j+1))|(1<<j)],dp[pre][s]+a[i][j]);
                    dp[now][s&(~(1<<j))&(~(1<<(j+1)))]=max(dp[now][s&(~(1<<j))&(~(1<<(j+1)))],dp[pre][s]);
//                    printf("
");
                }
                if (j==n-1)
                {
                    now^=1;pre^=1;
                    memset(dp[now],0,sizeof dp[now]);
                    F(s,0,(1<<(n+1))-1)
                    {
//                        print(s); printf(" --> "); print(((s<<1)&((1<<(n+1))-1))); printf("
");
                        dp[now][((s<<1)&((1<<(n+1))-1))]=max(dp[pre][s],dp[now][((s<<1)&((1<<(n+1))-1))]);
                    }
                }
//                printf("
");
            }
        int ans=0;
        F(s,0,(1<<(n+1))-1) ans=max(ans,dp[now][s]);
        printf("%d
",ans);
    }
}

  

原文地址:https://www.cnblogs.com/SfailSth/p/6435412.html