pku 1463 Strategic game 树形DP

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

对于树形DP不大来感啊,才开始做的时候考虑成覆盖全部点了,致使我拓扑做了,WA了好几次。感觉是树形DP好像以前做过类似的题目可是就是想不出来怎么做了,看来还是不扎实。最后搜了一下解题报告,对于每一点只有放与不放两种状态,如果这一点放了士兵那么他的临接点可以放也可以不放,如果这一点没有放那么他的临接点一定放了。

由此得出dp[i][0]+= dp[j][1]     dp[i][1] = min(dp[j][0],dp[j][1]) (j属于i的临接点) dp[i][0] 表示i点不放士兵 dp[i][1] 表示i 点放士兵。。随便由一点出发,进行dp..这里选择0 则最后结果就是min(dp[0][0],dp[0][1]);  用临界矩阵回TLE的,所以要用临界表

View Code
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define maxn 1507
using namespace std;

int dp[maxn][2];
int n;
vector<int>map[maxn];

bool isL(int x)
{
    if (map[x].size() == 1)
    return true;
    else
    return false;
}
void dfs(int pos,int f)
{
    int i;
    if (isL(pos) && f != -1)//注意这里f != -1 的判断
    {
        dp[pos][0] = 0;
        dp[pos][1] = 1;
        return ;
    }
    else
    {
        dp[pos][1]++;//注意要先加+1
        for (i = 0; i < map[pos].size(); ++i)
        {
            if (map[pos][i] != f)
            {
                int p = map[pos][i];
                dfs(p,pos);
                dp[pos][0] += dp[p][1];
                dp[pos][1] += min(dp[p][1],dp[p][0]);
            }
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
   int i,j;
   int x,y,m;
   while (~scanf("%d",&n))
   {
       for (i = 0; i < n; ++i)
       map[i].clear();
       memset(dp,0,sizeof(dp));
       for (i = 0; i < n; ++i)
       {
           scanf("%d:(%d)",&x,&m);
           for (j = 0; j < m; ++j)
           {
               scanf("%d",&y);
               map[x].push_back(y);
               map[y].push_back(x);
           }
       }
       dfs(0,-1);
       printf("%d\n",min(dp[0][0],dp[0][1]));
   }
    return 0;
}

 

 

posted @ 2012-04-23 20:51  E_star  阅读(192)  评论(0编辑  收藏  举报