您的位置:首页 > 大数据 > 人工智能

csu 2014 summer training day 4 树形dp升阶

2014-07-28 18:00 309 查看
POJ 1155

题意:电视台发送信号给很多用户,每个用户有愿意出的钱,电视台经过的路线都有一定费用,求电视台不损失的情况下最多给多少用户发送信号。

要知道用户都在叶子节点,费用消耗在使用选择的路径上,每条路径的使用费用给出,每个用户支付的费用给出。

输入:N为总节点数,M为用户数,1为电视台, 2 to N-M 是中转站,N-M+1到N是潜在用户

对于1到N-M的中继点,给出连接的点的个数K,K对(A,C)表示连接到A点,这条路径的费用是C

最后是M个整数,表示用户支付的费用

分析:

int num[maxn];//记录每个节点下面的总用户数
int dp[maxn][maxn];//i:i的子树中,j:节点下面的使用用户数,能达到的最大的剩余利润
//dp:最大剩余利润:线路费用-使用用户支付的费用
相当于树形背包:

dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]);
temp[j]表示原来的dp[u][j]
对于搜索出来的一棵树,对于它的孩子,可以选择加还是不加,其中len[u][i]恰好表示u到当前选择的v的代价

完整写法:

for(int j=0;j<=num[u];j++){
temp[j]=dp[u][j];
}
for(int j=0;j<=num[u];j++){
for(int k=1;k<=num[v];k++){//注意k!=0,否则多减少了i
dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v][k]-len[u][i]);
}
}
num[u]+=num[v];

代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#define MAXN 110
#define MAXK 220
using namespace std;

vector<int>G[MAXN];
int anum[MAXN];
int dp[MAXN][MAXK][2];
int N,K;
int temp[MAXN];
void dfs(int u,int fa){
dp[u][0][1]=anum[u];
dp[u][0][0]=anum[u];
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if (v==fa) {
continue;
}
dfs(v,u);
for(int j=K;j>=0;j--){
for(int t=1;t<=j;t++){
dp[u][j][0]=max(dp[u][j][0],dp[v][t-1][0]+dp[u][j-t][1]);
if (t==1) continue;
dp[u][j][0]=max(dp[u][j][0],dp[v][t-2][1]+dp[u][j-t][0]);
dp[u][j][1]=max(dp[u][j][1],dp[v][t-2][1]+dp[u][j-t][1]);
}
}
}

return ;
}
int main(){
while(~scanf("%d%d",&N,&K)){
for(int i=1;i<=N;i++){
scanf("%d",&anum[i]);
}
for(int i=0;i<=N;i++) G[i].clear();
for(int i=1;i<=N-1;i++){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
memset(dp,0,sizeof(dp));
for(int i=0;i<=N;i++){
for(int j=0;j<=K;j++) dp[i][j][0]=dp[i][j][1]=anum[i];
}
dfs(1,-1);
printf("%d\n",dp[1][K][0]);
}
return 0;
}


View Code

POJ 1947

POJ 1848

POJ 1655
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: