題目鏈結
給你乙個n*n的格仔的棋盤,每個格仔裡面有乙個非負數。
從中取出若干個數,使得任意的兩個數所在的格仔沒有公共邊,就是說所取的數所在的2個格仔不能相鄰,並且取出的數的和最大。
包括多個測試例項,每個測試例項包括乙個整數 n 和 n*n個非負數(n<=20)
對於每個測試例項,輸出可能取得的最大的和
3
75 15 21
75 15 28
34 70 5
188
典型的狀壓 dp ~
我們對每一列的取數可以用二進位制表示,有 n
nn 位顯然就是 [0,
2n
)[0,2^n)
[0,2n)
,那麼對相鄰的兩行 x,y
x,yx,
y 只需要判斷 x&y
=0
x\&y=0
x&y=
0 即可,如果等於 0
00 證明兩行無相鄰點。但此時複雜度還是太高了,我們想到一行中也不能存在相鄰點,也就是說這個數的二進位制裡不能有相鄰的 1
11,判斷只需用 x&(
x>
>1)
=0
x\&(x>>1)=0
x&(x
>
>1)
=0判斷即可,為什麼呢?因為只要二進位制中無連續的 1
11,該數與其錯一位後進行與運算一定等於 0
00,可以自己列幾個數字計算一下,這樣篩一下數後複雜度就能大幅降低,下面考慮 dp
我們用 dp[
i][j
]dp[i][j]
dp[i][
j]表示第 i
ii 行以 j
jj 作為該行狀態的最大值,cal
(i,j
)cal(i,j)
cal(i,
j)函式計算 i
ii 行以 j
jj 為狀態後的取值,那麼我們可以列舉 i−1
i-1i−
1 行所有符合條件的最大值加上 cal
(i,j
)cal(i,j)
cal(i,
j),即:dp[
i][j
]=ma
x(dp
[i][
j],d
p[i−
1][k
]+ca
l(i,
j)),
k&j=
0dp[i][j]=max(dp[i][j],dp[i-1][k]+cal(i,j)),k\&j=0
dp[i][
j]=m
ax(d
p[i]
[j],
dp[i
−1][
k]+c
al(i
,j))
,k&j
=0ac**如下:
#include
using
namespace std;
int n,a[20]
[1<<18]
,dp[20]
[1<<18]
;int num[
1<<18]
;int
cal(
int x,
int y)
return sum;
}int
main()
}}}for
(int i=
1;i<=cnt;i++
) ans=
max(ans,dp[n]
[i])
;printf
("%d\n"
,ans);}
return0;
}
HDU 1565 方格取數 1
hdu 1565 方格取數 1 我的第乙個狀態壓縮dp 給你乙個n n的格仔的棋盤,每個格仔裡面有乙個非負數,從中取出若干個數,使得任意的兩個數所在的格仔沒有公共邊,就是說所取的數所在的2個格仔不能相鄰,並且取出的數的和最大 3 75 15 21 75 15 28 34 70 5 188對於每乙個數...
HDU1565 方格取數 1
problem description 給你乙個n n的格仔的棋盤,每個格仔裡面有乙個非負數。從中取出若干個數,使得任意的兩個數所在的格仔沒有公共邊,就是說所取的數所在的2個格仔不能相鄰,並且取出的數的和最大。input 包括多個測試例項,每個測試例項包括乙個整數n 和n n個非負數 n 20 ou...
HDU 1565 方格取數 1
problem description 給你乙個n n的格仔的棋盤,每個格仔裡面有乙個非負數。從中取出若干個數,使得任意的兩個數所在的格仔沒有公共邊,就是說所取的數所在的2個格仔不能相鄰,並且取出的數的和最大。input 包括多個測試例項,每個測試例項包括乙個整數n 和n n個非負數 n 20 ou...