【UVA】1220-Party at Hali-Bula?(动态规划,树)

来源:互联网 发布:nginx重启命令 编辑:程序博客网 时间:2024/05/21 22:57

刚开始学树上的动规,感觉还是比较吃力,照着书上的思路敲出来了。

状态转移的话需要对每个结点定义2个状态dp[i][0]和dp[i][1]分别代表不选择i结点和选择i结点的情况下的最大人数。

这样的话,如果选择了i,也就是dp[i][1]的时候,他只能加上他儿子的儿子,也就是孙子。

dp[i][1] = sum{dp[son][0]};

  如果不选择i的话,他就有2个选择了

dp[i][0] = sum{max(dp[son][0],dp[son][1])};

判读是不是唯一解的话分2步,定义fp[i][0] 和 fp[i][1]代表这2个状态下是否解唯一。

在dp[i][1] = sum{dp[son][0]}; 的时候,如果 fp[son][0] = 0,也就是不唯一,那么fp[i][1] = 0,也不唯一。

在dp[i][0] = sum{max(dp[son][0],dp[son][1])};的时候比较复杂,分3个情况。

1.当 dp[son][0] = dp[son][1]的时候, fp[i][0] = 0; 不唯一。

2.当 dp[son][0] > dp[son][1]的时候,如果fp[son][0] = 0 ,fp[i][0] = 0;

3.当 dp[son][0] < dp[son][1]的时候,如果fp[son][1] = 0 ,fp[i][0] = 0;

140016121220Party at Hali-BulaAcceptedC++0.0182014-08-07 04:04:14


#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<stack>#include<queue>#include<map>#include<set>#include<list>#include<string>#include<sstream>#include<ctime>using namespace std;#define _PI acos(-1.0)#define INF 1 << 10#define esp 1e-6typedef long long LL;typedef unsigned long long ULL;typedef pair<int,int> pill;/*======================================================================================*/#define MAXD 200 + 10map<string,int>person;  /*员工姓名和编号*/vector<int>G[MAXD];int n;int size ,ans;int dp[MAXD][2];/*dp[c][1]代表在选c的情况下最多能选几个人,dp[c][0]代表不选c的时候能选几个人*/int fp[MAXD][2];/*fp[c][1]代表在选c的情况下方案是否唯一,同理fp[c][0]代表不选c的时候是否唯一*/bool Input(){    size = 1;    person.clear();    cin >> n;    if(!n)        return false;    string name;    string s1[MAXD],s2[MAXD];    cin >> name;    person[name] = size++;    for(int i = 0 ; i < n - 1; i++){         cin >> s1[i] >> s2[i];         if(!person[s1[i]])            person[s1[i]] = size++;         if(!person[s2[i]])            person[s2[i]] = size++;    }    size--;    for(int i = 1 ; i <= size ; i++)        G[i].clear();    for(int i = 0 ; i < n - 1 ; i++){         int x = person[s1[i]] , y = person[s2[i]];         G[y].push_back(x);    }    return true;}void DP(int pos){    if(G[pos].empty()){        dp[pos][0] = 0;        dp[pos][1] = 1;        fp[pos][0] = 1; /*边界条件方案都唯一*/        fp[pos][1] = 1;        return ;    }    dp[pos][0] = 0;    dp[pos][1] = 1;    fp[pos][0] = 1;    fp[pos][1] = 1;    for(int i = 0 ; i < G[pos].size() ; i++){        int son = G[pos][i];        DP(son);        if(fp[pos][1]){        if(!fp[son][0]) /*儿子里面有一个的方案不唯一*/            fp[pos][1] = 0;        }        if(fp[pos][0]){        if(dp[son][0] == dp[son][1]){            fp[pos][0] = 0;        }        else if(dp[son][0] > dp[son][1] && !dp[son][0])            fp[pos][0] = 0;        else if(dp[son][1] > dp[son][0] && !dp[son][1])            fp[pos][0] = 0;        }        dp[pos][1] += dp[son][0];        dp[pos][0]  = dp[pos][0] + max(dp[son][1],dp[son][0]);    }    return ;}int main(){    while(Input()){        DP(1);        if(dp[1][0] > dp[1][1]){            printf("%d ",dp[1][0]);            if(fp[1][0])                printf("Yes");            else                printf("No");        }        else if(dp[1][0] < dp[1][1]){            printf("%d ",dp[1][1]);            if(fp[1][1])                printf("Yes");            else                printf("No");        }        else{            printf("%d ",dp[1][1]);            printf("No");        }        printf("\n");    }    return 0;}


0 0
原创粉丝点击