第二篇:P1270
题解补完计划:第二篇
显然,原图是个二叉树。
我们考虑 DP。我们定义 \(dp_{i,j}\) 表示在 \(i\) 的子树内,偷 \(j\) 幅画的最小时间, 转移是 \(O(n^2)\) 的,然后注意一下读入就可以了。
#include<bits/stdc++.h>
using namespace std;
#define N 2005
#define intl long long
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
intl x=0,k=1;char ch=getchar();
while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*k;
}
intl sta[N], top, n, tim, dp[N][N],a[N], tmp[N];
vector<pair<intl,intl>> g[N];
void get(intl u) {
intl x = read(), y = read();
if(y) {
g[u].push_back({++n, x}), a[n] = y;
return ;
}
g[u].push_back({++n, x});
intl now = n;
get(now), get(now);
}
void dfs(intl u) {
if(g[u].empty()){
For(i,0,a[u]) dp[u][i]=i*5;
return;
}
if(u == 1){
dfs(g[u][0].first);
dp[u][0]=0;
For(i,1,600) dp[u][i] = dp[g[u][0].first][i] + g[u][0].second*2;
return;
}
dfs(g[u][0].first), dfs(g[u][1].first);
For(i,0,600) For(j,0,600-i){
intl lw=i?g[u][0].second:0,rw=j?g[u][1].second:0;
dp[u][i+j]=min(dp[u][i+j],dp[g[u][0].first][i]+dp[g[u][1].first][j]+lw*2+rw*2);
}
// cout << u << endl;
// For(i,0,600) cout <<dp[u][i] << " \n"[i == 600];
}
int main() {
tim = read();
get(++n);
memset(dp, 0x3f, sizeof dp);
dfs(1);
deo(i,600,0) if(dp[1][i] < tim) return printf("%lld\n", i), 0;
return 0;
}

浙公网安备 33010602011771号