2019 ICPC银川区域赛 Girls Band Party(分组背包)

You are currently playing a game called “Garupa”. In an event of the game, you are trying to get more event points. You have nn cards, each with its own name, color, and power. When you play the game, you can put five cards of different names into your deck. The base point of this event is the sum of the power of the cards in your deck. On top of that, the event publishes a color and five names as bonus attributes, which means that each time you have a card with a bonus color in the deck, you end up with a 20%20% increase in event point. And each time you have a card with a bonus name in the deck, you will eventually get 10%10% of the event point (bonus values are calculated by addition, and we round down when calculating the final event point). Please find the maximum event point you will eventually get.

Input
The first line is an integer T~(1 \leq T \leq 50T (1≤T≤50), which is the number of test cases.

For each set of input data, input a positive integer n~(5 \leq n \leq 100000)n (5≤n≤100000) in the first line to indicate the number of cards you have.

The next nn lines, the ii-th line input two strings name_iname
i

, color_icolor
i

and a positive integer power_i~(1 \leq power_i \leq 50000)power
i

(1≤power
i

≤50000) separated by spaces, indicating the name, color, and power of the ii-th card. The input data ensures that there are at least five cards with different names.

The next line input five strings representing the five bonus names. The input data guarantees that the bonus names are different.

The last line input a string representing a bonus color.

The input data ensures that all strings consist of only uppercase and lowercase letters and the max length of them is 1010, and the sum of nn in all sets of input data does not exceed 15000001500000.

Output
For each set of data, output only one line of a positive integer, indicating the maximum number of bonus points that you will eventually get.

样例输入复制
1
6
Saaya Power 45000
Kokoro Happy 45000
Kasumi Cool 45000
Rimi Power 45000
Aya Pure 45000
Aya Power 2000
Saaya Tae Kasumi Rimi Arisa
Power
样例输出复制
382500

题意:
每个物品有3个属性:名称 颜色 价值。
选中特定的名称会是总价值提升0.1倍,选中特定颜色会使总价值提升0.2倍
选5个不同名称物品使得价值和最大

思路:
状态很明显,就是选了多少个数字和提升了多少个0.1倍。将名称相同的物品放在一起,分组背包就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <map>
#include <vector>

using namespace std;

const int maxn = 1e5 + 7;

map<string,int>mp1,mp2;
int dp[maxn][6][16];

struct Node
{
    int val,num;
    string name,color;
    bool operator < (const Node&rhs)const
    {
        return name < rhs.name;
    }
}a[maxn];

vector<Node>G[maxn];

void init(int n)
{
    memset(dp,-1,sizeof(dp));
    mp1.clear();mp2.clear();
    for(int i = 1;i <= n;i++)G[i].clear();
}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n;scanf("%d",&n);
        init(n);
        for(int i = 1;i <= n;i++)
        {
            cin >> a[i].name >> a[i].color >> a[i].val;
        }
        
        string tmp;
        for(int i = 1;i <= 5;i++)
        {
            cin >> tmp;mp1[tmp] = 1;
        }
        cin >> tmp;mp2[tmp] = 2;
        
        sort(a + 1,a + 1 + n);
        int cnt = 0;
        for(int i = 1;i <= n;i++)
        {
            if(a[i].name != a[i - 1].name)
            {
                cnt++;
            }
            a[i].num = mp1[a[i].name] + mp2[a[i].color];
            G[cnt].push_back(a[i]);
//            cout << a[i].name << ' ' << a[i].color << ' ' << a[i].num << ' ' << a[i].val << endl;
        }
        
        dp[0][0][0] = 0;
        for(int i = 1;i <= cnt;i++)
        {
            for(int k = 0;k <= 5;k++)
            {
                for(int q = 0;q <= 15;q++)
                {
                    dp[i][k][q] = dp[i - 1][k][q];
                }
            }
            for(int j = 0;j < G[i].size();j++)
            {
                int val = G[i][j].val,num = G[i][j].num;
                
                for(int k = 1;k <= 5;k++)
                {
                    for(int q = num;q <= 15;q++)
                    {
                        if(dp[i - 1][k - 1][q - num] != -1)
                        {
                            dp[i][k][q] = max(dp[i][k][q],dp[i - 1][k - 1][q - num] + val);
                        }
                    }
                }
            }
        }
        
        int ans = 0;
        for(int i = 0;i <= 5;i++)
        {
            for(int j = 0;j <= 15;j++)
            {
                ans = max(ans,dp[cnt][i][j] * (10 + j) / 10);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

发布了756 篇原创文章 · 获赞 27 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/104651695