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\n");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("\n"); } 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("\n"); dp[now][((s<<1)&((1<<(n+1))-1))]=max(dp[pre][s],dp[now][((s<<1)&((1<<(n+1))-1))]); } } // printf("\n"); } int ans=0; F(s,0,(1<<(n+1))-1) ans=max(ans,dp[now][s]); printf("%d\n",ans); } }