1. 程式人生 > >簡單版的動態規劃

簡單版的動態規劃

問題描述

小北很喜歡玩計算機遊戲,特別是戰略遊戲,但是有時他不能儘快找到解所以常常感到很沮喪。現在面臨如下問題:他必須在一箇中世紀的城堡裡設防,城堡裡的道路形成一棵無向樹。要在結點上安排最少的士兵使得他們可以看到所有邊。你能幫助他嗎?

你的任務是給出士兵的最少數目。

輸入格式

輸入包含多組資料。每組資料表示一棵樹,在每組資料中:

第一行是結點的數目。

接下來的幾行,每行按如下格式描述一個結點:

結點識別符號 : ( 道路的數目 ) 結點識別符號1  結點識別符號......  結點識別符號道路的數目

或者

結點識別符號 : (0)

對於 n (0<n<=1500) 個結點,結點識別符號是一個從 0 到 n - 1 的整數。每條邊在測試用例中只出現一次。

輸出格式

對於每組資料,各給出一個整數表示士兵的最少數目.

測試輸入
4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)
測試輸出
1
2
原始碼
#include <stdio.h>  
#include <string.h>  
#define min(x,y) ((x>y)?y:x)  
#define N 1504   
int dp[N][2], father[N], v[N], n;  
int main()  
{  
    int i, j, k, t1, t2, root=0;  
    void DFS(int root);  
    while(scanf("%d",&n)!=EOF){  
        memset(dp,0,sizeof(dp));  
        memset(father,0,sizeof(father));  
        memset(v,0,sizeof(v));  
        for(i=0;i<n;i++){  
            scanf("%d:(%d)",&t1,&t2);  
            if(i==0) root=t1;  
            for(j=0;j<t2;j++){  
                scanf("%d",&k);  
                father[k]=t1;  
            }         
        }  
        DFS(root);  
        printf("%d\n",min(dp[root][0],dp[root][1]));  
    }  
    return 0;  
}  
  
void DFS(int root)  
{  
    v[root]=1;  
    for(int i=0;i<n;i++){  
        if(!v[i] && father[i]==root){  
            DFS(i);  
            dp[root][1]=dp[root][1]+dp[i][0];  
            dp[root][0]=dp[root][0]+min(dp[i][0],dp[i][1]);  
        }  
    }  
    dp[root][0]++;  
}