題意:還記得這題嗎?cf1332d 就是說乙個二維矩陣,從(1,1)走到(n,m),只能向下或右走,獲得的總貢獻是每一步的&運算,問你最後能獲得多少貢獻。
思路:我們很容易想到,dp[i][j]表示走到(i,j)的最大值,然後每步取大就行,但是這個方法是錯誤的,比如這個資料:
3 4按照這種dp,答案是2,但是其實我們可以得到的最大貢獻為3。因為我們要的是按位&的結果最大,但是可能到倒數第二步是有兩種,一種是1000,還有一種是0100,但是a[n][m]是0110,按照原來dp的思路,倒數第二步存了1000,和最後一步按位與之後,答案變成了0,但是如果倒數第二步是0100,這樣結果就是0100。7 3 3 1
4 8 3 6
7 7 7 3
所以我們要獲得最大價值,那麼首先應該考慮的是高位,因為2i >(2i-1 + 2i-2 +…+20 ) 所以這個貪心方案是正確的。
我們從高位到低位遍歷,之後再取低位的時候要首先滿足這條路符合之前的選擇。
我們用dp[i][j]表示在取第b位的時候能否走到(i,j),如果能,就從這個點出發,看是否能走下一步,最後如果這一位能走到(n,m),就把最後的總貢獻加上(1<#include
#define endl '\n'
#define null null
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair
#define ull unsigned long long
#define all(x) x.begin(),x.end()
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ct cerr<<"time elapsed:"<<1.0*clock()/clocks_per_sec<<"s.\n";
char
*fs,
*ft,buf[
1<<20]
;#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline
intread()
while
(ch>=
'0'&&ch<=
'9')
return x*f;
}using
namespace std;
const
int n=
1e3+5;
const
int inf=
0x3f3f3f3f
;const
int mod=
1e9+7;
const
double eps=
1e-7
;const
double pi=
acos(-
1);int a[n]
[n],dp[n]
[n];
signed
main()
int ans=0;
for(
int b=
31;b>=
0;b--)}
}if(dp[n]
[m]&&
(a[n]
[m]&(1
1<} cout<}
SCPC 普普通通的DP(字面意思)
給你乙個n m的矩陣,你需要從左上角走到右下角,你每次只能向下或者向右走,並且不能走出矩陣之外。只要你走到終點之後,你就會獲得獎勵,獎勵的金額為 所有經過的元素做 與 運算。算一算你能獲得的最大獎勵金額為多少。位置越高對答案影響越大,所以我們從高位到低位開始跑,計算每一位是否能有數字跑到最後且不影響...
數字DP 按位DP
之前說過要做個專題,雖然隔了好長時間。但說話還是算數的,把之前做的ppt翻出來貼上,好吧,我就是懶。見識的還是少,歡迎討論啊 數字dp 在給定區間 a,b 內,找滿足要求的數。要求一般和數大小無關,而與數的組成有關 例如,遞增的,1234,2579 雙峰的,19280,26193 含49的,49,1...
專題 數字DP 按位DP
自 數字dp 在給定區間 a,b 內,找滿足要求的數。要求一般和數大小無關,而與數的組成有關 例如,遞增的,1234,2579 雙峰的,19280,26193 含49的,49,149,1492 整除13的,26,39 麻煩在於,規模大,位數 100 不能列舉。區間往往不是整百整千,邊界問題 注意 記...