ZOJ 2834 樹形DP

2022-08-05 18:21:09 字數 1554 閱讀 4951

題目意思太羅嗦,不解釋了。這道題一開始一直segmentation fault,問了秦總才發現可能是陣列放在dfs裡面的關心後來又wa了無數次,結果是因為它居然可以是個森林!!!簡直報警了,題目中明明說的是koopa的所有兒子,居然還可以存在森林。唉。。。

這道題好事蠻不錯的一道題,每一個點有三種狀態:dp[i][0],dp[i][1],dp[i][2]。dp[i][1]代表第i個人剛剛被幹掉,第i個節點及其子樹的最大值。dp[i][0]代表第i個節點即所有節點的t[i]值之和。dp[i][2]代表的是第i個節點沒有被幹掉所能幹掉其子樹的最大值和。

下面來寫轉移方程:

dp[u][0] = t[u] + sum;

dp[u][2] = max = max+ sum; 這兩個v相互獨立

dp[u][1] = max + sum;

注意下一邊界條件就可以開始寫了。。。算 dp[v][0]-dp[v][2]+dp[w][1]-dp[w][2]的最大值的時候有一個小技巧,直接看我的**:

#include #include #include #include #include #define for(i,x,y) for(int i = x;i < y;i ++)

using namespace std;

const int maxn = 2222;

int n,dp[maxn][3],t[maxn],head[maxn],edge_cnt; //dp[i][0]表示i個節點和他的所有子樹都被殺了,dp[i][1]表示第一次i個節點被殺了,dp[i][2]表示i個節點沒被殺

int st[maxn];

struct edgeedge[maxn<<1];

bool cmp(int x,int y)

void add_edge(int u,int v)

void dfs(int u,int fa)

else dp01 = max(dp01,t[v]);

if(dp[v][1]-dp[v][2] >= dp10)

else dp11 = max(dp11,dp[v][1]-dp[v][2]);

dp2 = max(dp2,dp[v][0]-dp[v][2]+dp[v][1]-dp[v][2]);

cnt++;

}if(!cnt) return;

if(cnt == 1)

else

else

dp[u][1] += sum + dp00 + dp10;

dp[u][2] += sum+dp00;

}return;

}int dfs2(int u,int fa)

return ans;

}int main()

add_edge(i,to);

add_edge(to,i);

}int ans = 0;

for(i,0,st_cnt-1) ans += dfs2(st[i],-1);

dfs(n-1,-1);

printf("%d\n",ans+dp[n-1][1]);

}return 0;

}

ZOJ 1276 DP

給出一系列的1x2的矩陣,要你求出矩陣以什麼樣的次序相乘才使得相乘次數最少,。 不用排序,只要決定該矩陣是和前面相乘比較好,還是後面 。 今天仔細想了一下,跟之前做的dp題目做了下對比,你比如說猴子堆磚塊拿香蕉那題,那種是通過設定區域性量j 求得1到j的區域性最優解,再遞增j,直到求得全域性最優解 這種題...

ZOJ 3463 Piano dp

題目意思好毒瘤 很容易想到 dp 狀態 dp i j k 表示列舉到第 i 個位置,左大拇指在 j ,右大拇指在 k 的最少代價 對於每一個按鍵,直接列舉用哪個手去覆蓋即可 但是題目那個手不能覆蓋怎麼處理? 其實並不需要考慮,這種情況一定會被一種同樣優秀的方法替代掉 include include ...

ZOJ 3640 概率DP

題意 給定初始值為f 等概率相遇n種怪物 其相應值的c i 若當前值大於c i 達成的天數為t i 否則花一天升級c i 再t i 達成,求達成期望 注意到過程是逆序單調的 先初始化limit再倒過來遞推即可 include include include include include inclu...