昨天做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);
}
}