在dota中,有些装备可以直接买,有些装备要用装备合成,现在你已经有一些装备,若要使你有某些装备,则还需要花多少钱买?
题意不大清楚的地方:装备名字中没有空白符,可以合成的装备一定不能直接从商店买,装备最多只有一种合成图径(没有假腿这样的),装备合成方式不存在环(A+B->C,C+D->A),所有计算均不会超过int,现有的但是没用的装备不能卖
最开始想错了..没有考虑到现有的装备有可能用不上的情况..直接计算每个装备的价格然后用目标状态的价格减去现有状态的价格了...WA了好久...
直接把目标装备分解即可
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
using namespace std;
map <string,int> tr;
int n1,n2,n3,n4,p;
int have[110],is[110][110],cost[110],tmp[110];
bool com[110];
bool hasNext() {
for (int i=1;i<=p;i++) {
if (com[i]&&have[i]<0) return true;
}
return false;
}
void sub(int x,int n) {
//printf("---%d %d\n",x,n);
if (!com[x]||have[x]>=n) {
have[x]-=n;
return;
}
n-=have[x];
have[x]=0;
for (int i=1;i<p;i++) {
if (is[x][i]>0) sub(i,is[x][i]*n);
}
}
int main() {
int i,j;
int x,y;
char s[80];
while (scanf("%d",&n1)!=EOF) {
tr.clear();
memset(have,0,sizeof(have));
memset(cost,-1,sizeof(cost));
memset(com,0,sizeof(com));
memset(is,0,sizeof(is));
for (i=1;i<110;i++) is[i][i]=1;
p=1;
for (i=0;i<n1;i++) {
scanf("%s%d",s,&x);
if (tr[s]==0) tr[s]=p++;
cost[tr[s]]=x;
}
scanf("%d",&n2);
for (i=0;i<n2;i++) {
scanf("%s%d",s,&x);
if (tr[s]==0) tr[s]=p++;
have[tr[s]]=x;
}
scanf("%d",&n3);
for (i=0;i<n3;i++) {
int tmpmax=0;
memset(tmp,0,sizeof(tmp));
do {
scanf("%s",s);
if (tr[s]==0) tr[s]=p++;
int tmpx=tr[s];
tmpmax=tmpmax>tmpx?tmpmax:tmpx;
tmp[tmpx]++;
} while (scanf("%s",s),s[0]!='=');
scanf("%s",s);
if (tr[s]==0) tr[s]=p++;
x=tr[s];
for (j=1;j<p;j++) {
is[x][j]=tmp[j];
}
com[x]=true;
}
int ans=0;
scanf("%d",&n4);
for (i=0;i<n4;i++) {
scanf("%s%d",s,&x);
have[tr[s]]-=x;
}
//for (i=1;i<p;i++) printf("%d ",have[i]);
//printf("\n");
while (hasNext()) {
for (i=1;i<p;i++) {
if (com[i]&&have[i]<0) {
for (j=1;j<p;j++) {
have[j]+=is[i][j]*have[i];
}
have[i]=0;
}
}
}
for (i=1;i<p;i++) {
if (have[i]<0) ans-=cost[i]*have[i];
}
//for (i=1;i<p;i++) printf("%d ",have[i]);
//printf("\n");
printf("%d\n",ans);
}
return 0;
}