POJ3345 Bribing FIPA 【背包类树形dp】

题目链接

POJ

题解

背包树形dp板题
就是读入有点无聊,浪费了很多青春

#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<string>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define cls(s) memset(s,0,sizeof(s))
using namespace std;
const int maxn = 205,maxm = 50005,INF = 1000000000;
map<string,int> id;
int ls[maxn],rb[maxn],n,m,siz[maxn],fa[maxn],rt;
char s[maxm],name[maxn];
LL f[maxn][maxn],val[maxn];
void dfs(int u){
	f[u][0] = 0; siz[u] = 1;
	for (int k = ls[u]; k; k = rb[k]){
		dfs(k); siz[u] += siz[k];
		for (int i = n; i >= 0; i--)
			for (int j = 0; j <= i; j++)
				f[u][i] = min(f[u][i],f[u][i - j] + f[k][j]);
	}
	if (u != rt) f[u][siz[u]] = min(f[u][siz[u]],val[u]);
}
int main(){
	int idx,x;
	while(scanf("%s",s) > 0 && strcmp(s,"#") != 0){
		id.clear(); idx = 0;
		cls(fa); cls(rb); cls(ls); memset(f,0x3f3f3f3f,sizeof(f));
		scanf("%d",&m); n = 0;
		for(int i = 0; s[i] != ''; i++)  
			n = n * 10 + s[i] - '0';
		rt = n + 1;
		REP(i,n){
			scanf("%s%d",name,&x);
			if (id[name] == 0) id[name] = ++idx;
			int u = id[name],to; val[u] = x;
			while (getchar() != '
'){
				scanf("%s",name);  
                if (id[name] == 0) id[name] = ++idx;
                to = id[name];
                rb[to] = ls[u];
				ls[u] = to;
				fa[to] = u;
			}
		}
		REP(i,n) if (!fa[i]){
			fa[i] = rt;
			rb[i] = ls[rt];
			ls[rt] = i;
		}
		dfs(rt);
		LL ans = f[rt][m];
		for (int i = m + 1; i <= n; i++) ans = min(ans,f[rt][i]);
		cout << ans << endl;
	}
	return 0;
}

原文地址:https://www.cnblogs.com/Mychael/p/9020456.html