Codeforces 979B Treasure Hunt(贪心)

题目链接:Treasure Hunt

题意

Kuro K u r o Shiro S h i r o Katie K a t i e 三人都有一个长度相同的字符串,每个字符串都只包含小写字母和大写字母,三个人都有 n n 次对自己的字符串进行操作的机会,每次操作可以选择一个字符并将这个字符修改成另一个字符。一个字符串的价值定义为这个字符串中所有子串出现的最大次数,他们三人经过 n 轮操作后,在采取最优策略下,谁的字符串价值将会最大。

输入

第一行为一个整数 n (0n109) n   ( 0 ≤ n ≤ 10 9 ) ,接下去三行为三个字符串,分别为 Kuro,Shiro K u r o , S h i r o Katie K a t i e 的初始字符串,字符串的长度不超过 105 10 5 ,字符串只包含小写字母和大写字母。

输出

输出三人都采取最优策略下,字符串价值最大的人,如果存在两个或两个以上最大价值,输出 Draw D r a w

样例

输入
3
Kuroo
Shiro
Katie
输出
Kuro
提示
3 3 轮之后,Kuro 可以将自己的字符串修改为 ooooo,价值为 5 5 ,而另外两个人最多只能得到价值为 4 的字符串。
输入
7
treasurehunt
threefriends
hiCodeforces
输出
Shiro
输入
1
abcabc
cbabac
ababca
输出
Katie
输入
15
foPaErcvJ
mZaxowpbt
mkuOlaHRE
输出
Draw
提示
每个人都可以将自己的字符串修改成 9 9 个相同的字符,因此三人平局。

题解

如果某个长度大于 1 的子串是字符串中出现次数最多的子串,那么这个子串中的字符一定也是出现最多的子串,因此只要处理所有字符即可,对于每个人都计算出可能的最大价值再进行比较就能知道赢家。如果某个字符串的字符完全相等且 n n 等于 1,那么这个符串的价值只能等于 |s|1 | s | − 1 ,如果 Max+n|s| M a x + n ≤ | s | (其中 Max M a x 为字符出现的最大次数),那么最大价值就是 Max+n M a x + n ,否则字符串的价值就可以达到 |s| | s |

过题代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <algorithm>
using namespace std;

#define LL long long
const int maxn = 100000 + 100;
int n;
char str[3][maxn];
int score[3];
map<char, int> mp[3];
int len[3];
map<int, int> mpp;
map<int, int>::iterator it;

int getscore(int Index, char ch) {
    int tmp = n - (len[Index] - mp[Index][ch]);
    if(tmp >= 0) {
        if(mp[Index][ch] == len[Index] && tmp == 1) {
            return len[Index] - 1;
        }
        return len[Index];
    }
    return n + mp[Index][ch];
}

int main() {
    #ifdef LOCAL
    freopen("test.txt", "r", stdin);
//    freopen("10.out", "w", stdout);
    #endif // LOCAL

    while(scanf("%d", &n) != EOF) {
        mpp.clear();
        memset(score, 0, sizeof(score));
        for(int i = 0; i < 3; ++i) {
            mp[i].clear();
            scanf("%s", str[i]);
            len[i] = strlen(str[i]);
            for(int j = 0; str[i][j]; ++j) {
                ++mp[i][str[i][j]];
            }
        }
        for(char ch = 'a'; ch <= 'z'; ++ch) {
            for(int i = 0; i < 3; ++i) {
                score[i] = max(score[i], getscore(i, ch));
            }
        }
        for(char ch = 'A'; ch <= 'Z'; ++ch) {
            for(int i = 0; i < 3; ++i) {
                score[i] = max(score[i], getscore(i, ch));
            }
        }
        int Max = 0;
        for(int i = 0; i < 3; ++i) {
            Max = max(Max, score[i]);
            ++mpp[score[i]];
        }
        int cnt = 0;
        int ans = 0;
        for(int i = 0; i < 3; ++i) {
            if(score[i] == Max) {
                ++cnt;
                ans = i;
            }
        }
        if(cnt >= 2) {
            printf("Draw\n");
        } else {
            switch(ans) {
                case 0: printf("Kuro\n"); break;
                case 1: printf("Shiro\n"); break;
                case 2: printf("Katie\n"); break;
            }
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值