poj 3345 Bribing FIPA 樹形dp

poj 3345 Bribing FIPA

http://poj.org/problem?id=3345

題意,一個人想用錢賄賂一些國家獲得選票,賄賂不同的國家需要不同數量金錢,有些國家可控制另一些國家,也就是賄賂了這些國家,被他們控制國家的票也會投給這個人,無環,每個點最多有一個父節點,求得n張選票的最少花費

 

輸入真心噁心啊這個題……

之後就是樹形dp了,用了兩次dfs,第一次求出每個節點及其以下共有多少個,第二次求出最少花費,兩個可以合在一起寫的,只是這樣感覺更容易想寫

 

dp[p][j] = min(dp[p][j], dp[p][k] + dp[v[p][i]][j-k]);

dp[p][j]表示,在p及p的子樹中, 選j個國家,最少花費

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
const int maxn = 210;
const int INF = 0x3f3f3f3f;
int value, m, n, w[maxn], vis[maxn], dp[210][210], ans[maxn];
vector <int> v[maxn];
map<string, int> mp;
int count(int p){
    int i, j, k;
    ans[p] = 1;
    for( i= 0; i< v[p].size(); i++){
        ans[p] += count(v[p][i]);
    }
    return ans[p];
}
int dfs(int p){
    int i, j, k;
    for(  i= 1; i<= ans[p]; i++)
        dp[p][i] = w[p];
    dp[p][0] = 0;
    for( i= 0; i<v[p].size(); i++){
        dfs(v[p][i]);
        for( j= min(n, ans[p]); j>= 0; j--){
            for( k= 0; k<= j; k++){
                dp[p][j] = min(dp[p][j], dp[p][k] + dp[v[p][i]][j-k]);
            }
        }
    }
}
int main(){
	freopen("1.txt", "r", stdin);
	int i, j, k, tt, val;
	char tmp[110], tmp1[110], tmp2[110], ch;
    while( scanf("%s", tmp) && tmp[0] != '#' ){
        sscanf(tmp, "%d", &m);
        scanf("%d", &n);
        for( i= 0; i<= 200; i++) v[i].clear();
        mp.clear();
        memset( vis, 0, sizeof( vis));
        memset( ans, 0, sizeof( ans));
        memset( dp, 0x3f, sizeof( dp));
        for( i= 0, tt= 1; i< m; i++){
            scanf("%s%d", tmp, &val);
            if ( mp[tmp] == 0) mp[tmp] = tt++;
            w[mp[tmp]] = val;
            while( 1){
                while( scanf("%c", &ch)&& ch == ' ');
                if( ch == '\n' || ch == '#') break;
                else{
                    tmp1[0] = ch;
                    j= 1;
                    while( scanf("%c", &ch) && (ch!= ' ' && ch!= '\n' && ch!= '#'))
                        tmp1[j++] = ch;
                    tmp1[j] = '\0';
                    if( mp[tmp1] == 0) mp[tmp1] = tt++;
                    v[mp[tmp]].push_back(mp[tmp1]);
                    vis[mp[tmp1]] = 1;
                }
                if( ch == '\n') break;
            }
        }
        for( i= 1; i<= m; i++)
            if( !vis[i]) v[0].push_back(i);
        w[0] = INF;
       // cout<<mp["a"]<<mp["b"]<<mp["c"]<<mp["d"]<<mp["e"]<<mp["f"]<<mp["g"]<<mp["h"]<<mp["i"]<<endl;
        count(0);
        dfs(0);
        printf("%d\n", dp[0][n]);
        if( ch == '#') break;
    }
	return 0;
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章