[HDOJ 2677][Vjudge 27932] Dota all stars [模拟]

69 篇文章 0 订阅
9 篇文章 0 订阅

在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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值