今天唯一A的题……还是昨天的遗留问题T^T后天晚上就校赛了,一个小破题卡了这么久可怎么好
题目大意:一个人要竞选,需要贿赂别人投选票(真贴近实际),贿赂的人有从属关系,问至少多少钱能买至少m张票
搜这个题的时候看到了01背包的字样,然并卵,虎超超的在草纸上写了一个三维数组真是大错特错,其实分类中【二重dp】的字样是意味着”背包“而已。自己又纠结在有从属关系的表示上orz ,解决方法是:由于dfs时,先遍历子树,再返回根节点,这样,以i为根的子树中的节点可能被多次利用,解决办法就是访问到i时,先开一个tmp数组当前的状态,即dp值,然后访问子树,返回时,先更新tmp值,再用tmp值更新dp值。即 dp值是针对所有情况中的某点最优解,tmp是当前搜索的这个分支上的情况
再有就是字符串的处理sscanf getchar()从寒假就不熟,一直到现在处理字符串还依旧头痛;
背包部分的讲解:
for(int i=m+cnt[u];i>=cnt[u];i--)
{
tmp[i]=min(tmp[i-cnt[u]]+w[u],tmp[i]);
dp[i]=min(dp[i],tmp[i]);
}
u是当前的根节点,cnt[u]是以u为根的子树节点数即背包的容量(每次做背包都要卡在分辨谁是容量,谁是价值上也是醉)w[u]是贿赂的钱数
居然最后一次WA在了dp数组开小了一半,难道不应该是RE吗╮(╯_╰)╭
/*********
hdu2415
2015.12.27-12.28
0MS 2004K 2210 B G++
*********/
#include <iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
int n,m,tol;
map<string,int>name;
char str1[204];
int head[10000];
struct node
{
int from,to,next;
}edge[10000];
void addedge(int a,int b)
{
edge[tol].from=a;
edge[tol].to=b;
edge[tol].next=head[a];
head[a]=tol++;
}
int w[204],cnt[204],dp[450];
int min(int a,int b)
{
if(a<b) return a;
return b;
}
void dfs(int u)
{
int tmp[400];
cnt[u]=1;
memcpy(tmp,dp,sizeof(tmp));
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
dfs(v);
cnt[u]+=cnt[v];
}
for(int i=m+cnt[u];i>=cnt[u];i--)
{
tmp[i]=min(tmp[i-cnt[u]]+w[u],tmp[i]);
dp[i]=min(dp[i],tmp[i]);
}
}
int main()
{
// freopen("cin.txt","r",stdin);
while(gets(str1))
{
if(str1[0]=='#') break;
sscanf(str1,"%d%d",&n,&m);
name.clear();
bool is[240];
memset(is,0,sizeof(is));
memset(cnt,0,sizeof(cnt));
memset(dp,0x3f3f3f3f,sizeof(dp));
memset(head,-1,sizeof(head));
char str[400];
int idx=0,ttt;
tol=0;
for(int i=1;i<=n;i++)
{
scanf("%s%d",str,&ttt);
int k=name[str];
if(k==0)
{
name[str]=++idx;
k=idx;
}
w[k]=ttt;
//printf("%s:%d ",str,k);
char c=getchar();
while(c==' ')
{
scanf("%s",str);
int l=name[str];
if(l==0)
{
name[str]=++idx;
l=idx;
}
// printf("%s:%d ",str,l);
addedge(k,l);
is[l]=1;
c=getchar();
}
}
dp[0]=0;
for(int i=1;i<=n;i++) if(!is[i]) dfs(i);
int ans=0x3f3f3f3f;
for(int i=m;i<=n*2;i++)
{
ans=min(ans,dp[i]);
}
printf("%d\n",ans);
}
return 0;
}