COGS 613. 火车站饭店 解题报告

613. 火车站饭店

政府邀请了你在火车站开饭店,但不允许同时在两个相连的火车站开。任意两个火车站有且只有一条路径,每个火车站最多有 50 个和它相连接的火车站。

告诉你每个火车站的利润,问你可以获得的最大利润为多少?

例如下图是火车站网络:

最佳投资方案是 1 , 2 , 5 , 6 这 4 个火车站开饭店可以获得的利润为 90.


传送门

那么,这是本蒟蒻做的第一道树形DP。
树形DP一般用搜索实现,先处理子节点,再处理自身,最终得到整棵树的最优解,总是默认1为根节点。

本题中用dp[i][0]表示不选i节点时的最大获利,dp[i][1]表示选择i节点时的最大获利。

#include
#include
#include
using namespace std;
 
const int maxn = 100000 + 10;
int G[maxn][51], value[maxn], dp[maxn][2], waynum[maxn];
bool vis[maxn][51];
int n;
 
void Init(){
	scanf("%d",&n);
	for(int i = 1; i <= n; i++)scanf("%d",&value[i]);
	for(int i = 1; i <= n-1; i++){
		int x,y;
		scanf("%d%d",&x,&y);
		G[x][waynum[x]++] = y;
		G[y][waynum[y]++] = x;
	}
}
void DP(int pos){
	int temp(0), temp2(0);
	for(int i = 0; i < waynum[pos]; i++){
		if(!vis[pos][i]){
			for(int j = 0; j < waynum[G[pos][i]]; j++){
				if(G[G[pos][i]][j] == pos){
					vis[G[pos][i]][j] = 1;//标记是否访问过
					break;
				}
			}
			DP(G[pos][i]);//与pos相连的某个节点(pos的儿子之一)
			temp2 += dp[G[pos][i]][0];//不选以pos为根的子树
			temp += max(dp[G[pos][i]][1],dp[G[pos][i]][0]);//在选与不选中取较大的
		}
	}
	dp[pos][0] = temp;//不选pos节点
	dp[pos][1] = temp2 + value[pos];//选pos节点
}
int main(){
	#ifndef DEBUG
		string FileName="profitz";
		freopen((FileName+".in").c_str(),"r",stdin);
		freopen((FileName+".out").c_str(),"w",stdout);
	#endif
	Init();
	DP(1);
	printf("%d",max(dp[1][0],dp[1][1]));
} 


你可能感兴趣的:(DFS,动态规划,树形DP)