HZOI 可憐與超市 樹形dp

2022-04-14 07:27:12 字數 1119 閱讀 5871

學長留的題,質量還是灰常高的。

而且我樹規本身較弱,一道也不想放下

題解:這道題我們可以看出是乙個樹形結構,而且是dp

dp首先要定義狀態

設$dp[i][j][0/1]$表示當前考慮到第i個物品(以i為根的子樹中),買了j個物品的代價,0表示不用i的優惠券,1表示使用

初始狀態:$dp[i][1][1]=c[i]-d[i],dp[i][1][0]=c[i],dp[i][0][0]=0$,其他都是最大值

目標:$ans=max(i),(dp[1][i][1]<=b)$

轉移:  $dp[x][j+k][1]=min(dp[x][j][1]+min(dp[y][k][0],dp[y][k][1]))$

$dp[x][j+k][0]=min(dp[x][j][0]+dp[y][k][0])$

x表示當前節點,y表示當前搜尋到的x的兒子,j是列舉的當前x的size,k是列舉的y的size

方程的話,你看看它代表什麼就能理解了

有人說要特判k=0時的情況,因為如果你用優惠券,就必須買這個產品,所以沒有dp[i][0][1]這種情況

但其實初始狀態中我們把它設成了最大值,所以不會對結果有影響

上**:

#include#include#include#include#define maxn 5005

#define ll long long

using namespace std;

ll n,b,c[maxn],d[maxn],x[maxn],ans=0;

ll to[maxn<<1],nxt[maxn<<1],pre[maxn],cnt=0;

void add(ll u,ll v)

int size[maxn],dp[maxn][maxn][2];//dp[i][j][0/1]:以i為子樹,買了j個的價錢,0為不用券,1為用券,

void dfs(ll rt)

} size[rt]+=size[y]; }}

int main()

dfs(1);

for(ll i=1;i<=n;i++)

printf("%lld\n",ans);

return 0;

}

可憐與超市

t4 可憐與超市 long long 我看到10的九次方了,我直接龍龍 不對啊,b也小於10億啊,int就夠了 我聰明的大腦瞬間看出,樹形dp 題幹的意思是不是1就是根?應該是,但我覺得不穩 f u 0 1 以u為根的子樹,u買或者不買的能購買的最多商品 最優解 之所以這麼定義因為跑不了10億乘50...

TJOI2017 城市 樹形dp

這是個神仙題,會卡常 題目讓你改一條邊把直徑變得最短。列舉每條邊,會把圖分成兩個地方,兩個連通塊 x區和y區域 都換根dp一下,算出離x最遠的點的距離記為dis x 然後列舉一下 新直徑有三個 1 max dis x x裡面最大的 2 dis y y裡面最大的 3 min dis x dis y l...

樹上揹包 可憐與超市

發現商品間的關係顯然是棵樹,所以做樹上揹包。發現商品的 都很高不能放在狀態裡,而價值都是1,所以轉換維度。定義 dp u j 0 1 為在 u 的子樹中選出 j 個物品所需要的最小 其中0代表不用優惠券買u,1代表用優惠券買u。轉移 sum sum dp u j k 1 min dp u j k 1...