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;

}

 

 

你可能感兴趣的:(game)