POJ3345 Bribing FIPA(樹形DP)

題目大意:

一個國家想賄賂至少m個國家,給出賄賂每個國家需要的錢及他們的附屬關係。如果賄賂了主國,其附屬國家也同樣視爲被賄賂了,且保證關係網沒環,和一個國家最多隻能被一個國家控制。

題目思路:本題要用到樹形揹包和字符串處理,字符串用普通方法讀入特別麻煩且代碼繁瑣。這裏我第一次用到了map:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
using namespace std;
map<string,int>a;//定義map(下標爲字符串方便操作)
int u[205],f[205],m[205][205],d[205][205],n,o,t[205];
char h[205],r[205];
int dfs(int x){//深搜
    int i,j,k;
    int ans=1;
    if(x==0)ans=0;
    if(u[x]==1&&x>0){
        d[x][0]=0;
        d[x][1]=f[x];
        return 1;
    }
    for(i=1;i<=n;i++)
        if(m[x][i]==0)
        ans+=dfs(i);//將結果相加
    d[x][0]=0;
    for(i=1;i<=n;i++){
        if(m[x][i]==-1) continue;  
        for(k=n;k>=0;k--)//揹包
            for(j=1;j<=k;j++){
                if(d[x][k-j]!=-1&& d[i][j]!=-1){
                     if(d[x][k]!=-1)
                         d[x][k]=min(d[x][k],d[x][k-j]+d[i][j]);
                     else 
                         d[x][k]=d[x][k-j]+d[i][j];
                }
            }
    } 
    if(d[x][ans]==-1||d[x][ans]>f[x])
              d[x][ans]=f[x]; 
        return ans;
}
int lily(){//因爲有可能是'#'所以字符讀入
    char c=getchar();
    int s=0;
      while(c<'0'||c>'9')  
    {  
        if(c=='#')return 0;  //當爲'#'時返回'0';
        c=getchar();  
    }  
    while(c>='0'&&c<='9')  
    {  
        s*=10;  
        s+=c-'0';  
        c=getchar();  
    }  
    return s;  
}
int main(void){
    int i,j,k,g;
    char c;
    while(1){
         n=lily();//讀入n
         if(n==0)break;//當n爲'0'結束
         scanf("%d",&o);
         memset(m,-1,sizeof(m));
         memset(t,0,sizeof(t));
         getchar();
         k=1;
         for(i=1;i<=n;i++){//記錄
            scanf("%s",h);
            scanf("%d",&g);
            if(!a[h])
                a[h]=k++;
            f[a[h]]=g;
            u[a[h]]=1;
            c=getchar();
            while(c!='\n'){
                scanf("%s",r);
                if(!a[r]){
                    a[r]=k++;
                 }
                m[a[h]][a[r]]=0;
                t[a[r]]++;
                u[a[h]]++;
                c=getchar();
             }
         }
         f[0]=0;
         u[0]=1;
         for(i=1;i<=n;i++){
            if(t[i]==0){
                m[0][i]=0;
                u[0]++;
                f[0]+=f[i];
             }
         }
         memset(d,-1,sizeof(d));  //清空
         dfs(0);//搜索
         int max=10000000;
         for(j=o;j<=n;j++){
             if(d[0][j]!=-1 &&d[0][j]<max){
                max=d[0][j];
             }  
         }  
         printf("%d\n",max);//輸出
         a.clear();//清空
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章