奮戰杭電ACM(DAY9)1011

開學了,用電腦時間愈來愈少,軍校一大麻煩,班長還特別賤,心情極度很差。發火直接發題,儘可能寫註釋。node

Starship Troopers

#include<iostream>
using namespace std;

const int MAXN=110;
int N,M;

struct Node
{
    int number,p;//p:該結點的possible;number:該結點的bug數
};
Node node[MAXN];//記錄結點 

int dp[MAXN][MAXN];//DP,dp[i][j]表示跟結點爲i時,用掉j個士兵得到的最大值 
int adj[MAXN][MAXN];//存樹 。adj[i][j]:結點爲i,adj[i][0]表示該結點所鏈接的結點(父結點和子結點一共)個數
                    //adj[i][j](j>=1)表示結點編號,j=結點個數+1
bool vis[MAXN];//訪問標記 

int max(int a, int b)
{
    return a>b ? a:b;
}

void dfs(int root)//DFS,求該結點及其分支所能得到的最大possible
{
    vis[root]=true;//已經訪問 
    int num=(node[root].number+19)/20;//得到該結點須要的士兵數目 
    for(int i=num;i<=M;i++)  dp[root][i]=node[root].p;//用掉i個士兵得到的possible
    for(i=1;i<=adj[root][0];i++)
    {
        int u=adj[root][i];
        if(vis[u]) continue;//跳過已訪問的,包括該結點的父節點和子結點
        dfs(u);//求該子結點的最大possible
        for(int j=M;j>=num;j--)
        {
            for(int k=1;j+k<=M;k++)//剩餘的士兵
            {
                if(dp[u][k])//該子結點的最大possible
                  dp[root][j+k]=max(dp[root][j+k],dp[root][j]+dp[u][k]);//j+k:父節點和子結點共用了士兵數目
                                                                        //dp[root][j+k]父結點和前i-1個子結點中所獲possible的最大值
                                                                        //dp[root][j]+dp[u][k]父結點和當前子結點u一共所獲possible
                                                                        //用來找出全部子結點裏能獲得的最大possible
                                                                        //即該父結點能獲得的最大possible
            }    
        }    
    }    
}  

int main()
{
    int b,e;
    while(cin >> N >> M)
    {
        if(N==-1&&M==-1) break;
        memset(vis,false,sizeof(vis));
        memset(dp,0,sizeof(dp));
        memset(adj,0,sizeof(adj));
        for(int i=1;i<=N;i++)
            cin >> node[i].number >>node[i].p;
        for(i=1;i<N;i++)//存圖 
        {
             cin >> b >> e;//鏈接結點b和e
             adj[b][0]++;
             adj[b][adj[b][0]]=e;
             adj[e][0]++;
             adj[e][adj[e][0]]=b;
        }
        if(M==0)//這個必須要,有代價爲0的房間,M=0則沒法得到 
          cout << 0 << endl;
        else
        {
            dfs(1);
            cout << dp[1][M] << endl;
        }    

    } 
    return 0;   
}     
相關文章
相關標籤/搜索