POJ Strategic game(树形DP)

来源:互联网 发布:ubuntu 文本输入设置 编辑:程序博客网 时间:2024/05/16 06:18

题目链接:http://poj.org/problem?id=1463

其实这个题目也是比较水的一个树状DP,和上面一篇博客思路基本上差不多,甚至动态方程都差不多

开始建立树的时候,直接建立树,建树的时候直接让大的成为小的子树,由于题目说了这是一棵树,所以

就不用担心直接建树就好了,最后从0(根)号节点DFS即可!

每个子树的根节点可有两个状态,要么安排士兵要么不安排,如果安排,那么子节点可以安排也可以不安排

如果不安排,那么子节点就要安排,这个其实不好证明,但是能想得通!

本质上是从叶子节点向根节点递推的,贪心的想一下叶子节点是不会放士兵的,那么只要上上一层不放士兵,

那么上一层就一定要放!

#include <iostream>#include <string.h>#include <stdio.h>#include <stdio.h>#include <vector>#define maxn 2000#define MIN(a,b) (a<b?a:b)#define MAX(a,b) (a>b?a:b)using namespace std;int n,m;struct point{    int clu,exu;    vector<int> child;}po[maxn];int tree_dp(int root){    po[root].clu=1;    if(po[root].child.empty()){       po[root].exu=0;       return 0;    }    for(int i=0;i<po[root].child.size();i++){        tree_dp(po[root].child[i]);    }    for(int i=0;i<po[root].child.size();i++){        po[root].clu+=MIN(po[po[root].child[i]].clu,po[po[root].child[i]].exu);        po[root].exu+=po[po[root].child[i]].clu;    }    return 0;}int main(){    int i,j,k,a,b;    while(scanf("%d",&n)!=EOF){        for(i=0;i<n;i++) po[i].child.clear(),po[i].clu=po[i].exu=0;        for(i=0;i<n;i++){            scanf("%d:(%d)",&a,&m);            for(j=0;j<m;j++){                scanf("%d",&b);                if(a>b)po[b].child.push_back(a);                else po[a].child.push_back(b);            }        }        tree_dp(0);        printf("%d\n",MIN(po[0].clu,po[0].exu));    }    return 0;}


原创粉丝点击