HDU 2415 树形DP

来源:互联网 发布:数据库添加数据 编辑:程序博客网 时间:2024/05/21 19:29

题意

有N个国家,我们要获得M个国家的选票,我们可以贿赂一些国家。如果贿赂一个国家的统治国家,那么它统治的所有国家的选票都可以获得。贿赂一个国家需要一些钻石,问最少需要多少个钻石。

题解

其实是比较容易想的,只是数据格式好坑啊。这里强烈推荐一个函数。

sscanf(ch,"%d%d",&n,&m);

这个函数可以按一定格式读取一个字符串。做这道题可以方便一些。
我用的是strtok,一个字符串分割函数,也可以使用,但是不是很方便。
处理完成以后,我们发现这是一个森林,不太好处理,我们可以搞一个虚根,将森林转化为树。剩下的就是一个比较基础的背包问题了,要么选择这个点,要么就选择一些子点,如果选择这个点的话,可以直接获得所有的选票(num)。最后遍历一下大于等于M的最低花费就可以了。

注意事项

这里一个卡了好久的坑,我一直认为背包上限设置为M就可以了,但是WA了好久以后才发现,背包上限要设置为N,因为可能存在两个树不满M,但是合起来满M,而且最优的情况,如果上限为M的话,就相当于把这个情况自动过滤掉了。

代码

#include <bits/stdc++.h>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(t) while(t)#define MEM(a,b) memset(a,b,sizeof(a))#define MAXN 2200#define INF 0x3f3f3f3f#define LL long longusing namespace std;int n,m;int val[MAXN];bool son[MAXN];int dp[MAXN][MAXN];char ch[1000010];int cnt;map<string,int> mp;vector<int> vc[MAXN];int dfs(int u) {    dp[u][0]=0;    int num=1;    for(int x:vc[u]) {        num+=dfs(x);        DOWN(i,n+1,0) UP(j,0,i+1) dp[u][i]=min(dp[u][i],dp[u][i-j]+dp[x][j]);    }    dp[u][num]=min(dp[u][num],val[u]);    return num;}int main() {    ios::sync_with_stdio(false);    W(cin>>n>>m) {        cnt=1;        MEM(vc,0);        MEM(dp,INF);        MEM(son,false);        mp.clear();        val[1]=INF;        cin.getline(ch,1000000);        UP(i,0,n) {            cin.getline(ch,1000000);            char *c;            int pos=2;            int now;            c=strtok(ch," ");            string s=c;            if(mp[s]==0) mp[s]=++cnt,now=cnt;            else now=mp[s];            W(true) {                c=strtok(NULL," ");                if(c==NULL) break;                if(pos==2) {                    pos++;                    val[now]=atoi(c);                }else{                    string s=c;                    if(mp[s]==0) mp[s]=++cnt,vc[now].push_back(cnt);                    else vc[now].push_back(mp[s]);                    son[mp[s]]=true;                }            }        }        UP(i,2,cnt+1) if(!son[i]) vc[1].push_back(i);        dfs(1);        int ans=INF;        UP(i,m,n+1) ans=min(ans,dp[1][i]);        printf("%d\n",ans);    }}
原创粉丝点击