×

第二篇: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;
}


posted @ 2026-10-05 17:21  shiori123  阅读(6)  评论(0)    收藏  举报