HDU 1565 方格取數(1)(插頭DP||狀態壓縮)
阿新 • • 發佈:2019-01-30
Problem Description
給你一個n*n的格子的棋盤,每個格子裡面有一個非負數。
從中取出若干個數,使得任意的兩個數所在的格子沒有公共邊,就是說所取的數所在的2個格子不能相鄰,並且取出的數的和最大。
Input 包括多個測試例項,每個測試例項包括一個整數n 和n*n個非負數(n<=20)
Output 對於每個測試例項,輸出可能取得的最大的和
Sample Input 3 75 15 21 75 15 28 34 70 5
Sample Output 188
2程式碼:
從中取出若干個數,使得任意的兩個數所在的格子沒有公共邊,就是說所取的數所在的2個格子不能相鄰,並且取出的數的和最大。
Input 包括多個測試例項,每個測試例項包括一個整數n 和n*n個非負數(n<=20)
Output 對於每個測試例項,輸出可能取得的最大的和
Sample Input 3 75 15 21 75 15 28 34 70 5
Sample Output 188
1 ,狀態壓縮DP解法:把每一行的狀態用一個數的2進製表示,1為取,0為不取,每一行往下轉移就行了。O(N * 2^N * 2^N) 剪枝之後只有700ms左右
2,輪廓線DP解法:一格一格轉移,輪廓線用狀態壓縮表示,1為不取,0為取,O(N * N * 2^N) 耗時2000ms左右,
1程式碼:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <stack> #include <map> #include <set> #include <vector> #include <queue> #define mem(p,k) memset(p,k,sizeof(p)); #define rep(a,b,c) for(int a=b;a<c;a++) #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define ll long long #define inf 0x3f3f3f3f using namespace std; const int maxn=10; int t,n,m,ans,len,maxx; int mapp[22][22],dp[2][1<<21],plan[1<<21]; int ct(int x,int i){ int sum=0,cur=0; while(i){ if(i&1){ sum+=mapp[x][cur]; } i>>=1; cur++; } return sum; } void init(){ len=0; for(int i=0;i<1<<n;i++){ if(!(i&i<<1)){ dp[0][len]=ct(0,i); maxx=max(maxx,dp[0][len]); plan[len++]=i; } } } int main() { while(~scanf("%d",&n)){ for(int i=0;i<n;i++){ for(int j=0;j<n;j++)scanf("%d",mapp[i]+j); } maxx=0; init(); int now=0; for(int i=1;i<n;i++){ now^=1; mem(dp[now],0); for(int j=0;j<len;j++){ for(int k=0;k<len;k++){ if(!(plan[j]&plan[k])){ dp[now][j]=max(dp[now][j],dp[now^1][k]); } } dp[now][j]+=ct(i,plan[j]); maxx=max(dp[now][j],maxx); } } cout<<maxx<<endl; } return 0; }
2程式碼:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <stack> #include <map> #include <set> #include <vector> #include <queue> #define mem(p,k) memset(p,k,sizeof(p)); #define rep(a,b,c) for(int a=b;a<c;a++) #define pb push_back #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define ll long long #define inf 0x3f3f3f3f using namespace std; const int maxn=10; int t,n,m,ans,len,maxx; int mapp[22][22],dp[2][1<<21]; int main() { while(~scanf("%d",&n)){ for(int i=0;i<n;i++){ for(int j=0;j<n;j++)scanf("%d",mapp[i]+j); } int now=0; maxx=0; mem(dp,-1); dp[now][(1<<n)-1]=0; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ now^=1; mem(dp[now],-1); for(int k=0;k<1<<n;k++){ if(dp[now^1][k]<0)continue; dp[now][k|1<<j]=max(dp[now][k|1<<j],dp[now^1][k]); if(1<<j&k && (j==0 || 1<<(j-1)&k)){ dp[now][k^1<<j]=max(dp[now][k^1<<j],dp[now^1][k]+mapp[i][j]); } } } } for(int i=0;i<1<<n;i++)maxx=max(maxx,dp[now][i]); cout<<maxx<<endl; } return 0; }