网易游戏2017互娱实习笔试编程(强化装备)

题目描述
网游中,装备强化是提升角色战力的常见方法。 现在你参与开发的游戏中也有这项功能,团队正在设计每件装备强化所能提升的战力及需要消耗的金币数。为了设计出一个合理的强化系统,决定先做一些强化模拟测试,而你现在就在是该模拟程序的开发者。 假设现在有n件可以同时穿戴的装备,对于第i件装备,最多可以强化mi 次,对于第i件装备的第j次强化,会增加fij 的战力,并需要消耗gij 个金币。现在给出所有装备的数据,以及初始拥有的金币数量,求最多可以增加多少战力。
输入描述:
输入文件的第一行为一个正整数T,表示测试数据组数。
接下来有T组数据。每组数据第1行为两个整数n和s,分别表示装备数量及初始拥有的金币数量。接下来是n行,每行表示一个装备,其中每行第一项为一个字符串,表示装备的名称,第二项为非负整数mi,表示装备最多可强化的次数,接下来为2*mi个非负整数,表示每次强化会增加的战力及消耗的金币数。

数据范围:
对于所有数据文件,1<=T<=10。装备的名称最大长度不超过32个字符,由大小写字母或数字组成。每件装备最多强化次数mi满足0<=mi<=3。所有战力数值和金币数为非负整数且不超过10,000,000。
对于其中的20%数据,满足装备数1<=n<=5;
另外有30%数据,满足装备数1<=n<=10;
另外有30%数据,满足装备数1<=n<=16;
最后剩下的20%数据,满足装备数1<=n<=20。

数据保证只有唯一的强化方案能达到最大战力。

输出描述:
对于每个测试数据,第一行为一个整数,表示最多可提升的战力。接下来是n行,表示达到这个战力时每件装备分别的强化次数,形式为“装备名称+强化次数”。输出装备的顺序要与输入数据一致。更详细的格式请参照输出样例。

输入例子:
3
4 100
Helm 1 20 30
Gloves 1 30 40
Boots 1 10 10
Sword 1 50 50
5 10
Item1 0
Item2 1 10000 100
Item3 1 10 10
Item4 3 1 0 2 1 3 2
Item5 3 0 4 1 1 5 1
6 256
1x 2 12 43 35 58
2x 2 34 54 88 31
3x 2 43 10 15 55
4x 2 32 54 19 19
5x 2 84 1 15 45
6x 2 19 40 99 12

输出例子:
90
Helm+0
Gloves+1
Boots+1
Sword+1
12
Item1+0
Item2+0
Item3+0
Item4+3
Item5+3
418
1x+0
2x+2
3x+1
4x+2
5x+1
6x+2

代码(深度搜索,这个应该可以通过50%case(考试时因为写错一个变量,一直0.00%,修改后的代码通过示例),n>=10时可能会超时):

#include<vector>
#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;

struct Equipment{
    std::string name;
    int mi;
    std::vector<int> adds, consumes;
};

int maxAdd = 0;
std::vector<int> maxStrenNum;

void dfs(const std::vector<Equipment>& equipments, int eIndex, int qIndex, int goldRemain, std::vector<int>& strenNum, int totalAdds){
    if (eIndex == equipments.size()){
        if (totalAdds > maxAdd){
            maxAdd = totalAdds;
            maxStrenNum = strenNum;
        }
        return;
    }
    if (equipments[eIndex].mi == 0 || qIndex >= equipments[eIndex].mi)
        dfs(equipments, eIndex + 1, 0, goldRemain, strenNum, totalAdds);
    else{
        for (int i = qIndex; i < equipments[eIndex].mi; ++i){
            const int remain = goldRemain - equipments[eIndex].consumes[i];
            if (remain >= 0){
                strenNum[eIndex]++;
                dfs(equipments, eIndex, i + 1, remain, strenNum, totalAdds + equipments[eIndex].adds[i]);
                /* DEBUG80多分钟一直没找出问题,就因为将i+1写出qIndex+1,悔死我了 */
                strenNum[eIndex]--;
            }
        }
        dfs(equipments, eIndex + 1, 0, goldRemain, strenNum, totalAdds);
    }
}

void print(const std::vector<Equipment>& equipments){
    std::cout << maxAdd << std::endl;
    for (int i = 0; i < maxStrenNum.size(); ++i){
        int qNum = maxStrenNum[i];
        std::cout << equipments[i].name << "+" << qNum << std::endl;
    }
}

int main(){
    int looper = 0;
    std::cin >> looper;
    for (int i = 0; i < looper; ++i){
        int equipmentNum = 0, gNum = 0;
        std::cin >> equipmentNum >> gNum;
        std::vector<Equipment> equipments(equipmentNum);
        for (int k = 0; k < equipmentNum; ++k){
            std::cin >> equipments[k].name >> equipments[k].mi;
            for (int j = 0; j < equipments[k].mi; ++j){
                int adds, consumes;
                std::cin >> adds >> consumes;
                equipments[k].adds.push_back(adds);
                equipments[k].consumes.push_back(consumes);
            }
        }

        std::vector<int> strenNum(equipmentNum, 0);
        dfs(equipments, 0, 0, gNum, strenNum, 0);

        print(equipments);

        maxAdd = 0;
        maxStrenNum.clear();
    }

    system("pause");
    return 0;
}

代码(dp,其实这个问题是一个变化了的背包问题,关键在于如何处理成背包问题并求解):

#include<vector>
#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;

struct Equipment{
    std::string name;
    int mi;
};

int main(){
    int looper = 0;
    std::cin >> looper;
    for (int i = 0; i < looper; ++i){
        int equipmentNum = 0, gNum = 0;
        std::cin >> equipmentNum >> gNum;
        std::vector<Equipment> equipments(equipmentNum);
        std::vector<int> bIndex;
        std::vector<int> adds, consumes;
        for (int k = 0; k < equipmentNum; ++k){
            std::cin >> equipments[k].name >> equipments[k].mi;
            for (int j = 0; j < equipments[k].mi; ++j){
                int add, consume;
                std::cin >> add >> consume;
                adds.push_back(add);
                consumes.push_back(consume);
                bIndex.push_back(k);
            }
        }

        std::vector<std::vector<int>> dp(bIndex.size(), std::vector<int>(gNum + 1, 0));
        int maxAdds = 0;

        for (int k = consumes[0]; k <= gNum; ++k) dp[0][k] = adds[0];

        for (int k = 1; k < dp.size(); ++k){
            for (int j = consumes[k]; j <= gNum; ++j){
                dp[k][j] = std::max(dp[k - 1][j], dp[k - 1][j - consumes[k]] + adds[k]);
                maxAdds = std::max(maxAdds, dp[k][j]);
            }
        }
        int count = dp.back().back();
        std::vector<int> result(equipmentNum, 0);
        int colIndex = dp.front().size() - 1;
        for (int k = dp.size() - 1; k >= 0 && count != 0; --k){
            if (k != 0 && dp[k][colIndex] == dp[k - 1][colIndex - consumes[k]] + adds[k]){
                colIndex -= consumes[k];
                count -= adds[k];
                result[bIndex[k]]++;
            }
        }
        std::cout << maxAdds << std::endl;
        for (int i = 0; i < result.size(); ++i){
            std::cout << equipments[i].name << "+" << std::to_string(result[i]) << std::endl;
        }
    }
    system("pause");
    return 0;
}

总结:
1.题目的第三个示例存在问题,题目给出的是418,但自己的代码跑出来是434,而且验证了可以达到的最大战力是434;
2.做题时思路很重要,我就是做题按套路做,没有明确的思路,导致DEBUG那么久,一直没有找到问题,导致最后只A了一道(能不能面试都是个问题了,哭);
3.如果平时刷题没有当做上机来对待,机试时很容易因为紧张而各种出错;
4.最后,但愿能有面试。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值