[HDU] 1054 Strategic Game 入门树形DP

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1054

方法:一个节点选了,则其直接子节点可选可不选,一个节点没有选,则直接子节点必须选,所以建议状态转移方程设

F(P,0)为没有选择p点最少要用多少点,

F(P,1)为选择p点最少要用多少点

      {

      sum({F(S,1)|S是p的直接子节点});P为非叶子

F(P,0)=

      0;P为叶子

      },

      {

      sum({  min(F(S,1),F(S,0)) |S是p的直接子节点 })+1;P为非叶子

F(P,1)=

      1;P为叶子

      }

原来问题的解是min(F(root,1),F(root,0)).

注意这种输入方式如何确定root

代码:

#include <iostream>
#include <queue>
#include<algorithm>
using namespace std;
int n,m,MAX=1600;
bool map[1501][1501];
struct Arc
{
    int vetex;
    Arc* nextArc;
};
struct Node
{
    int x;
    int inDegree;
    Arc* firstArc;
    int layer;
	int noChose;
	int chose;
};
Node nodes[1501];
void createArc(int s,int e)
{
    Arc* arc = (Arc*)malloc(sizeof(Arc));
    arc->vetex=e;
    if(nodes[s].firstArc==NULL)
        arc->nextArc=NULL;
    else
        arc->nextArc=nodes[s].firstArc;
    nodes[s].firstArc = arc;
}
int treeDP[2000][2];
int myMin(int x,int y)
{
    return x>y ? y:x;
}
void treeDp(int root)
{
	Arc* arc = nodes[root].firstArc;
	int v,sonCount=0;
	while(arc!=NULL)
	{
		v=arc->vetex;
		treeDp(v);
		nodes[root].noChose += nodes[v].chose;
		nodes[root].chose += myMin(nodes[v].chose,nodes[v].noChose);
		arc=arc->nextArc;
		sonCount++;
	}
	if(sonCount == 0)
	{
		nodes[root].noChose = 0;  
		nodes[root].chose = 1;
	}
}
void main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(treeDP,0,sizeof(treeDP));
        for(int i=0;i<n;i++)
        {
            nodes[i].inDegree=0;
            nodes[i].firstArc=NULL;
			nodes[i].noChose = 0;
			nodes[i].chose = 1;
        }
        for(int i=0;i<n;i++)
        {
            char str[20];
            cin>>str;
            int number=0,posLeft,count=0;
            for(int i=0;i<::strlen(str);i++)
            {
                if(str[i]==':')
                {
                    int seed =1;
                    for(int k =i-1;k>=0;k--)
                    {
                        number+=(seed*(str[k]-'0'));
                        seed*=10;
                    }
                }
                if(str[i]=='(')
                    posLeft=i;
                if(str[i]==')')
                {
                    int seed =1;
                    for(int k = i-1;k>posLeft;k--)
                    {
                        count+=(seed*(str[k]-'0'));
                        seed*=10;
                    }
                }
            }
            nodes[number].x=number;
            for(int y=0;y<count;y++)
            {
                int son;
                cin>>son;
                nodes[son].x=son;
                nodes[son].inDegree++;
                createArc(number,son);
            }
        }

        for(int i=0;i<n;i++)
        {
            if(nodes[i].inDegree==0)
            {
                nodes[i].layer=0;
                treeDp(i);
				cout<<myMin(nodes[i].noChose,nodes[i].chose)<<endl;
                break;
            }
        } 
    }
}

 感想:入门水题

posted @ 2013-08-07 15:24  kbyd  阅读(179)  评论(0编辑  收藏  举报