hdu4269 Defend Jian Ge(模拟)

Defend Jian Ge

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 677    Accepted Submission(s): 141


Problem Description
Defend Jian Ge, an interesting RPG map in WAR3, has a very complete equipment system as a mini RPG game.
In the game, each player has a backpack which has 6 grids and some gold reserves. There are three kinds of equipments in the game.
1. Normal equipment: Each equipment occupies one grid in the backpack and the player can buy it directly. The value of the normal equipment is equal to its price.
2. Mixture equipment: Each equipment occupies one grid in the backpack and the player can only get it through the synthesis of the corresponding recipe. If you have enough equipment of recipes in your backpack and gold to pay synthesis cost, you can get it. The value of the mixture equipment is equal to the sum of all equipments’ value in the recipe plus the synthesis cost. A mixture equipment can be made from several normal equipments and mixture equipments.
3. Consume equipment: A kind of equipment must occupy one grid and the player can buy it directly. That is to say, if you have a number of consume equipments, they must be in one grid. The value of each consume equipment is equal to its price, and when you want to sell this kind of equipment, you must sell the whole grid's equipments at the same time.



You should pay attention:
1. When the backpack is full, you cannot buy anything.
2. When a mixture equipment is get, the mixture equipment of recipe in you backpack will disappear.
3. If one operation is illegal, there is nothing happened in your backpack and gold.
4. Initially, there is nothing in your backpack and you have 0 gold.
5. The gold you have cannot be a negative number.

As a DS programmer, you want to simulate the dynamic states in your backpack by program. Now you have initial state and several operations, you wonder the final state.
 

Input
There are multiple test cases.
The first line contains an integer N1 (0 <= N1 <= 20) indicating the kind of normal equipment.
The next N1 lines each line contains a string and an integer indicating the name of this normal equipment and its price respectively.
**Format: str num
The following line contains an integer N2 (0 <= N2 <= 20) indicating the kind of mixture equipment.
Each of the next N2 lines begins with a string and an integer indicating the name of this mixture equipment and its synthesis cost. Following, the synthesis recipe of this kind of equipment: some pairs of string and integer indicating which kind of equipment and the number you need to synthesis.
**Format: str num: str1 num1, str2 num2, ... , strn numn (num1 + num2 + … +numn<=6 and numi >= 0 (1 <= i <= n))
The next line contains an integer N3 (0 <= N3 <= 20) indicating the kind of consume equipment.
Each of the next N3 lines contains a string and an integer indicating the name of this consume equipment and it's price.
**Format: str num
The next line contains an integer M (0 <= M <= 100) indicating the number of operation.
Each of the next M lines contains an operation.
There are three kinds of operation:
1. +num indicating you get num gold (0 <= num <= 1000).
2. +str indicating you want to get an equipment whose name is str.
3. -str indicating you want to sell the equipment whose name is str. If you sell the equipment, you can get gold that is the same to its value.

There is a blank line after each case.
All strings of name only contain lowercase character and its length is no more than 15. The price of the equipment is a non-negative integer which is no more than 1000.
 

Output
For each case you should output several lines.
The first line output "Case " + case number + ":".
The next line output an integer indicating the number of gold at last.
The next line output an integer k indicating how many grids occupied.
Each of the next k lines contain a string and an integer indicating the name and the number of the equipment. You should output according to the lexicographic.
**Format: str: num

You can get more details from the sample below.
NOTE: Output a blank line after each test case.
 

Sample Input
  
  
[pre]2 ring 1 sword 2 1 knife 3: ring 1, sword 1 1 medicine 1 4 +100 +ring +sword +knife 1 shoe 0 1 wing 1: 1 medicine 1 3 +10 +shoe +wing 1 shoe 0 1 wing 1: 1 medicine 1 4 +10 +shoe +wing -wing 1 shoe 1 1 wing 1: shoe 1 1 medicine 1 8 +100 +shoe +shoe +shoe +shoe +shoe +medicine +medicine [/pre]
 

Sample Output
  
  
[pre]Case 1: 94 1 knife: 1 Case 2: 9 2 shoe: 1 wing: 1 Case 3: 10 1 shoe: 1 Case 4: 94 6 medicine: 1 shoe: 1 shoe: 1 shoe: 1 shoe: 1 shoe: 1 [/pre]
 

Source

变态模拟,各种蛋疼,无力吐槽,内牛满面。。。。

跪了将近一天了,虽然也犯了一些SB错误,但是这题的描述严重有问题。

先翻译一下此题:

题目大意:

1、初始状态一个背包,6个格子,一个钱包,一开始背包是空的,钱包也是空的
2、一共3种装备
3、普通装备:一个普通装备在背包占一个格子,可以直接买,价值就是它的价钱
4、合成装备:一个占一格,不可以直接买,根据处方合成,必须有足够的处方上的装备
以及足够的金币,它的价值是所有原料装备价值和合成所要的金币和,可以由普通装备
和合成装备合成。
5、消耗装备:一种占一格,可以直接买。如果要卖这种装备,必须卖掉所有该装备
还要注意:
1、背包满了就不能买东西了(可以合成)
2、 When a mixture equipment is get, the mixture equipment of recipe in you backpack will disappear:当合成了一个合成装备,它的处方会消失,即只能合成一次//这句话难道翻译错了?这样处理是错的
3、如果某操作非法,则该操作无效。不影响背包和金币。
4、初始背包空的,无金币
5、金币数不能为负
输入:
第一行0<=N1<=20,普通装备的数量
接下来N1行   每行一个字符串一个数字,分别表示普通装备的名字和价钱
然后0<=N2<=20,混合装备的数量
接下来N2行,每行先一个字符串一个数字,分别表示混合装备的名字和合成花费
然后给一个列表,表示合成此装备的原料及数量,总数不超过6个
再给一个0<=N3<=20,表示消耗装备的数量
接下来N3行,每行一个字符串一个数字,分别表示消耗装备的名字和价钱
再给一个M,表示操作总数
一共三种操作:
1:++num,表示得到num的金钱(0<=num<=100)
2:++str,表示想得到名叫str的装备
3:--str,表示想卖掉叫str的装备,得到相应的金币
每个名字都由小写字母组成,长度不超过15,每种装备的价钱为不超过1000的正整数
输出:
先输出Case #
然后输出最后的金币数
再输出还有几种装备
依次字典序输出这k种装备
输出空行

题目分析:模拟。输入就比较搞人,特别是合成装备,可以不需要原料直接合成的,那么就直接当普通装备处理。还有合成装备的原料的个数可以为0的。。。就是说需要这种原料,但是并不消耗这种原料。还有买消耗装备的时候,必须先买再合并的,如果背包是满的也是不能买的。


这算是一道比较好的模拟,但是坑爹的题目描述瞬间拉低了这题的档次。。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct norequ
{
    char name[16];
    int price;
}normal[21];

struct obj
{
    char name[16];
    int num,price;
    friend bool operator < (struct obj a,struct obj b)
    {
        return strcmp(a.name,b.name) < 0;
    }
}Obj[7];
int total;
bool del[10];
struct mix
{
    char name[16];
    int cost;
    int cnt;
    bool flag;
    int num[6];//原料数量
    char sname[6][16];//原料名
}mixture[21];

struct con
{
    char name[16];
    int price;
}consume[21];
int gold;
int m;
char equp[20];
int nornum,mixnum,connum;

void show()
{
    printf("Let's show:\n");
    int i,j;
    printf("normal:\n");
    for(i = 0;i < nornum;i ++)
        printf("%s  %d\n",normal[i].name,normal[i].price);
    printf("\n");
    printf("mixture:\n");
    for(i = 0;i < mixnum;i ++)
    {
        printf("%s  %d\n",mixture[i].name,mixture[i].cost);
        printf("the %dth mixture is consist of:\n",i);
        for(j = 0;j < mixture[i].cnt;j ++)
            printf("%s %d\n",mixture[i].sname[j],mixture[i].num[j]);
    }
    printf("\n");
    printf("consume:\n");
    for(i = 0;i < connum;i ++)
    {
        printf("%s %d\n",consume[i].name,consume[i].price);
    }
    printf("Show off\n");
}

void output(int cas)
{
    printf("Case %d:\n",cas);
    printf("%d\n",gold);
    printf("%d\n",total);
    sort(Obj,Obj + total);
    for(int i = 0;i < total;i ++)
        printf("%s: %d\n",Obj[i].name,Obj[i].num);
    putchar(10);
}

int find(char sss[])//找到物品种类
{
    int i;
    for(i = 0;i < nornum;i ++)
    {
        if(strcmp(sss,normal[i].name) == 0)
            return i;
    }
    for(i = 0;i < mixnum;i ++)
    {
        if(strcmp(sss,mixture[i].name) == 0)
            return 30 + i;
    }
    for(i = 0;i < connum;i ++)
    {
        if(strcmp(sss,consume[i].name) == 0)
            return 60 + i;
    }
    return -1;
}

int canmix(int id)
{
    if(mixture[id].cnt == 0)
        return 0;
    int i,j,k;
    int ret = 0;
    bool lll = false;
    for(i = 0;i < mixture[id].cnt;i ++)
    {
        k = mixture[id].num[i];
        for(j = 0;j < total;j ++)
        {
            if(strcmp(mixture[id].sname[i],Obj[j].name) == 0)
            {
                if(Obj[j].num <= mixture[id].num[i])//合成的时候
                {//有原料消耗,才能将合成物品放进背包
                    lll = true;
                }
                k -= Obj[j].num;
            }
            if(k <= 0)//原料足够
                break;
        }
        if(k > 0)//原料是不够的
            return -1;
    }
    if(lll = false && total == 6)//如果背包是满的但是原料不能腾出位置,也是不能合成的
        return -1;
    return 0;
}

void mixit(int id)
{
    if(mixture[id].cnt == 0)
        return;
    int i,j,k;
    memset(del,false,sizeof(del));
    for(i = 0;i < mixture[id].cnt;i ++)
    {
        k = mixture[id].num[i];
        if(!k)
            continue;
        for(j = 0;j < total;j ++)
        {
            if(strcmp(mixture[id].sname[i],Obj[j].name) == 0)
            {
                if(Obj[j].num > k)
                {
                    Obj[j].num -= k;
                    k = 0;
                }
                else
                {
                    del[j] = true;//要删除的做标记
                    k -= Obj[j].num;
                }
                if(k == 0)
                    break;
            }
        }
    }
    int pos = 0;
    for(i = 0;i < total;i ++)
    {
        if(del[i] == false)
            Obj[pos ++] = Obj[i];
    }
    total = pos;
}

int getprice(int type)//因为合成物品的原料也可以是合成物品,要递归计算价值
{
    if(type < 30)
        return normal[type].price;
    if(type >= 60)
        return consume[type - 60].price;
    int i;
    int ret = 0;
    for(i = 0;i < mixture[type - 30].cnt;i ++)
    {
        int tmp = find(mixture[type - 30].sname[i]);
        ret += mixture[type - 30].num[i] * getprice(tmp);
    }
    return ret + mixture[type - 30].cost;
}

void buy(int type)
{
    if(type < 30)
    {
        if(total == 6 || gold < normal[type].price)
            return;
        strcpy(Obj[total].name,normal[type].name);
        Obj[total].num = 1;
        Obj[total].price = normal[type].price;
        total ++;
        gold -= normal[type].price;
        return;
    }
    if(type >= 30 && type < 60)// mixture[type - 30].flag)
    {
        if(gold < mixture[type - 30].cost)//只需要付合成的钱
            return;
        int tmp = canmix(type - 30);
        if(tmp == -1)
            return;
        tmp = getprice(type);
        gold -= mixture[type - 30].cost;
        mixit(type - 30);
        Obj[total].price = tmp;
        Obj[total].num = 1;
        strcpy(Obj[total].name,mixture[type - 30].name);
        total ++;
        mixture[type - 30].flag = false;//only once
    }
    if(type >= 60)
    {
        if(total == 6 || gold < consume[type - 60].price)//消耗品先买再合并
            return;
        gold -= consume[type - 60].price;
        for(int i = 0;i < total;i ++)
        {
            if(strcmp(Obj[i].name,equp) == 0)
            {
                Obj[i].num ++;
                return;
            }
        }
        strcpy(Obj[total].name,consume[type - 60].name);
        Obj[total].num = 1;
        Obj[total].price = consume[type - 60].price;
        total ++;
        return;
    }
}

void sell(int type)
{
    int i;
    for(i = 0;i < total;i ++)
    {
        if(strcmp(equp,Obj[i].name) == 0)
            break;
    }
    if(i == total)//unfind
        return;
    if(type < 30)
    {
        gold += Obj[i].price;
        for(int j = i + 1;j < total;j ++)
            Obj[j - 1] = Obj[j];
        total --;
        return;
    }
    if(type >= 30 && type < 60)
    {
        gold += Obj[i].price;
        for(int j = i + 1;j < total;j ++)
            Obj[j - 1] = Obj[j];
        total --;
        return;
    }
    if(type >= 60)
    {
        gold += Obj[i].price * Obj[i].num;
        for(int j = i + 1;j < total;j ++)
            Obj[j - 1] = Obj[j];
        total --;
        return;
    }
}

int main()
{
    int i;
    char c;
    char op[20];
    int cas = 0;
    while(scanf("%d",&nornum) != EOF)
    {
        gold = 0;
        total = 0;
        for(i = 0;i < nornum;i ++)
        {
            scanf("%s%d",normal[i].name,&normal[i].price);
        }
        scanf("%d",&mixnum);
        getchar();
        for(i = 0;i < mixnum;i ++)
        {
            char str[200];
            gets(str);//还好有sscanf
            int p = 0;
            int tmp = 0;
            sscanf(str + p,"%s%d",mixture[i].name,&mixture[i].cost);
            while(str[p] && str[p] != ' ')
                p ++;
            p ++;
            while(str[p] && str[p] != ' ')
                p ++;
            while(sscanf(str + p,"%s%d",mixture[i].sname[tmp],&mixture[i].num[tmp]) == 2)
            {
                tmp ++;
                if(mixture[i].num[tmp - 1] == 0)
                    tmp --;
                while(str[p] && str[p] == ' ')
                    p ++;
                while(str[p] && str[p] != ' ')
                    p ++;
                p ++;
                while(str[p] && str[p] != ' ')
                    p ++;
            }
            mixture[i].cnt = tmp;
            mixture[i].flag = true;
        }
        scanf("%d",&connum);
        for(i = 0;i < connum;i ++)
        {
            scanf("%s%d",consume[i].name,&consume[i].price);
        }
        //show();
        scanf("%d",&m);
        getchar();
        while(m --)
        {
            gets(op);
            if(isdigit(op[1]))
            {
                sscanf(op + 1,"%d",&i);
                if(op[0] == '+')
                    gold += i;
                else
                {
                    if(gold >= i)
                        gold -= i;
                }
            }
            else
            {
                sscanf(op + 1,"%s",equp);
                int type = find(equp);
                if(type == -1)
                    continue;
                if(op[0] == '+')
                    buy(type);
                else
                    sell(type);
            }
        }
        output(++ cas);
    }
    return 0;
}
//0MS	260K
/*
2
ring 1
sword 2
1
knife 3: ring 1, sword 1
1
medicine 1
5
+100
+ring
+ring
+sword
+knife
2
ring 1
sword 2
1
knife 3: ring 1, sword 1
1
medicine 1
4
+100
+ring
+sword
+knife

1
shoe 0
1
wing 1:
1
medicine 1
3
+10
+shoe
+wing

1
shoe 0
1
wing 1:
1
medicine 1
4
+10
+shoe
+wing
-wing

1
shoe 1
1
wing 1: shoe 1
1
medicine 1
8
+100
+shoe
+shoe
+shoe
+shoe
+shoe
+medicine
+medicine


2
ring 1
sword 2
1
knife 3: ring 1, sword 1
1
medicine 1
4
+100
+ring
+sword
+knife

2
ring 1
sword 2
1
knife 3: ring 2, sword 1
1
medicine 1
5
+100
+ring
+ring
+sword
+knife

2
ring 1
sword 2
1
knife 3: ring 1, sword 1
1
medicine 1
5
+100
+ring
+sword
+knife
-knife

2
ring 1
sword 2
1
knife 3: ring 1, sword 1
1
medicine 1
5
+100
+ring
+sword
+knife
-sword

1
shoe 0
1
wing 1:
1
medicine 1
3
+10
+shoe
+wing

1
shoe 0
1
wing 1:
1
medicine 1
4
+10
+shoe
+wing
-wing

1
shoe 1
1
wing 1: shoe 1
1
medicine 1
7
+100
+shoe
+shoe
+shoe
+shoe
+medicine
+medicine

1
shoe 1
1
wing 1: shoe 1
1
medicine 1
8
+100
+shoe
+shoe
+shoe
+shoe
+medicine
+medicine
-medicine

*/



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值