[POJ1947]Rebuilding Roads解题报告

昨天做DotR的时候刚说以后泛化背包一定要写优化,然后今天又看见一个泛化背包,然后就扯犊子了。。(幸亏从讨论区里搞了一组数据。。)

注意到泛化背包可以优化的条件是什么?这其实跟它状态有关,只有当它保存的状态是最多花费价值时,才可以优化。。如果是严格的花费价值,显然是不能优化的!结果我一不小心又思维定势了。。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
inline void in(int &x){
	char c=getchar();
	while(c<'0'||c>'9')c=getchar();
	x=0;
	for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
}

int bag[155][155];
int sum[155];
int son[155][155];
int N,P;
#define inf 1000000000
int ans=inf;
bool root[155];
int Root;
inline void dfs(int node){
	int i;
	sum[node]=1;
	for(i=son[node][0];i;--i)dfs(son[node][i]);
	int j,k;
	//printf("-----%d------\n",node);
	if(son[node][0]){
		sum[node]+=sum[son[node][son[node][0]]];
		for(i=sum[node];i;--i)bag[node][i]=bag[son[node][son[node][0]]][i-1];
		bag[node][1]=1;
		/*printf("%d:",sum[node]);
		for(i=1;i<=sum[node];++i)printf("%d ",bag[node][i]);
		puts("");*/
		for(k=son[node][0];--k;){
			sum[node]+=sum[son[node][k]];
			for(i=sum[node];i;--i){
				++bag[node][i];
				for(j=min(sum[son[node][k]],i);j;--j)bag[node][i]=min(bag[node][i],bag[node][i-j]+bag[son[node][k]][j]);
			}
			/*printf("%d:",sum[node]);
			for(i=1;i<=sum[node];++i)printf("%d ",bag[node][i]);
			puts("");*/
		}
	}
	else bag[node][1]=0;
	/*printf("%d:",sum[node]);
	for(i=1;i<=sum[node];++i)printf("%d ",bag[node][i]);
	puts("");*/
	/*for(i=1;i<=sum[node];++i)printf("%d ",bag[node][i]);
	puts("");*/
	if(sum[node]>=P)ans=min(ans,bag[node][P]+(node!=Root));
}
int main(){
	freopen("poj_1947.in","r",stdin);
	freopen("poj_1947.out","w",stdout);
	in(N),in(P);
	if(P==0){
		puts("0");
		return 0;
	}
	memset(root,1,sizeof(root));
	memset(bag,60,sizeof(bag));
	for(int i=N,u,v;--i;){
		in(u),in(v);
		son[u][++son[u][0]]=v;
		root[v]=0;
	}
	for(int i=N;i;--i)
		if(root[i]){
			Root=i;
			dfs(i);
			printf("%d\n",ans);
		}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值