poj1463 Strategic game

1题目描述很简单。。其实就是求最小点覆盖。。但是。。。他明确说明是树。。如果用矩阵存储。。然后用匈牙利,显然不仅浪费空间。还浪费时间。。TLE了。。。

然后用邻接表。。可以AC了。。。

但是效率还是不高啊。。

这是一道最典型节点覆盖问题,这类可以用树形DP解。

对于顶点i,有两种状态,有士兵,没士兵,将这种状态下以i为根的子树的总士兵数为dp[i][0],dp[i][1]。

显然,如果i点没有士兵,那么它的所有子节点一定要有士兵,否则中间的线不能被覆盖。

所以dp[i][0]=dp[j0][1]+dp[j1][1]+...+dp[jk][1],其中j1,j2,...,jk是i的所有子节点。

如果i点有士兵,那么它的任意子节点都可以有士兵或没有士兵。

所以dp[i][1]=min(dp[j0][0],dp[j0][1])+min(dp[j1][0],dp[j1][1])+...+min(dp[jk][0],dp[jk][1])+1.

对于叶子节点,dp[i][0]=0,dp[i][1]=1

以上就是动态规划的状态转移方程。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
#define MIN(a,b) ((a)<(b)?(a):(b))
#define N 1505
#define M 11
typedef struct 
{
	int sum0,sum1;
}Sum;
Sum save;
typedef struct node 
{
	int count;
	struct node * next[M];
	
}tree;
Sum dp(tree * root)
{
	Sum s;
	int i;
	s.sum0=0;
	s.sum1=1;
	for(i=0;i<root->count;i++)
	{
		save=dp(root->next[i]);
		s.sum0+=save.sum1;
		s.sum1+=MIN(save.sum1,save.sum0);
	}
	return s;
}
int main(void)
{
	int n,a,m,i,j,v;
	tree t[N],*root;
	Sum ans;
	while(scanf("%d",&n)!=EOF)
	{
		memset(t,0,sizeof(t));
		root=NULL;
		for(i=0;i<n;i++)
		{
			scanf("%d:(%d)",&a,&m);
			t[a].count=m;
			if(root==NULL)
			{
				root=&t[a];
			}
			for(j=0;j<m;j++)
			{
				scanf("%d",&v);
				t[a].next[j]=&t[v];
			}
		}

		ans=dp(root);
		printf("%d\n",MIN(ans.sum0,ans.sum1));
	}
	return 0;
}


转载于:https://www.cnblogs.com/int32bit/archive/2011/07/29/3187796.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值