12186 - Another Crisis(工人的请愿书z )

树形DP 。 这是一棵树,且是由树根自顶向下递归出来的,所以每个节点只访问一次,因此连记忆化都不需要。      这里有一个小技巧: 最少需要的员工数量c = (k*t - 1) / 100 + 1

这样保证了唯一的一种特殊情况是正确的,特殊情况就是k*t是100的整数倍,比如:k = 20 , t = 20 那么如果不减1结果是5   而实际上最少只要4个人 。

当然我们还可以用一个函数:ceil(c)   作用是求出不小于实数c的最小整数 。

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<cmath>
using namespace std;
const int maxn = 100000 +5;
int n,t,a;
vector<int> sons[maxn];
int dp(int u) {
    if(sons[u].empty()) return 1;
    int k = sons[u].size();
    vector<int> d;
    for(int i=0;i<k;i++)
        d.push_back(dp(sons[u][i]));
    sort(d.begin(),d.end());
    int c = (k*t - 1) / 100 + 1;
    int ans = 0;
    for(int i=0;i<c;i++) ans += d[i];
    return ans;
}
int main() {
    while(~scanf("%d%d",&n,&t)) {
        if(!n&&!t) return 0;
        for(int i=1;i<=n;i++) {
            scanf("%d",&a);
            sons[a].push_back(i);
        }
        printf("%d\n",dp(0));
        for(int i=0;i<=n;i++) sons[i].clear();
    }
    return 0;
}



你可能感兴趣的:(12186 - Another Crisis(工人的请愿书z ))