codeforces 551b[补]

BNUZ比赛训练【补】

很久没写过博客了,今天捡起来继续写,之前懒,写完题之后不写题解,导致有些题做了无用功,最近开始了集训,没想到第一次集训竟然吊死在一个div2的b上,简直惨不忍睹。。这题b真的有毒

题目如下:
http://codeforces.com/problemset/problem/551/B

大致意思为:
给你三个串a,b,c,需要用a串里的字符使得b,c串在a串中出现次数之和最多。

乍一眼看一道小小的贪心,比赛的时候,一开始敲,就用了三个26的数组把他们字符统计一次,然后用第一个字符数模拟的除去第二个字符数,求出第二个最多可以构成的串,去掉最多构成的串*串的每一个字符数后之后再求第三个可以构成的串,同理求在第三个串出现最多的情况下,第二个串能出现多少次,然后相加取最大,结果。。就一直wa到了比赛结束test12。
期间做过了各种处理,让出现最多的从大到小再模拟求一次,看看能不能通过减少一个串来让另一个串增大数量。但是貌似还是wa在了test12。。然后就放弃了

正确的思路。只是当时想到了时间复杂度,不是很敢那样敲。。结果真是。。。
先把b,c串可以构成的最大数量求出来,若b大于c数量则用b的数量模拟,若c大于b的数量则用c的数量模拟,就每一次减少制造一个b或c串,然后再去看另一个串的数量,求他们之和,如果变大了,则采取这种方式(我当时写了个break,因为想着的是,如果你减少一个串都不能增加另一个串的话,肯定得要结束了)


真的是感觉最近自己菜到不行,辣么,就闲话不多说下面附上代码加一组最容易wa的数据。

aacaacbbaac
aac
ab
如果用贪心的话明显只能构成三串,但是实际上他可以构成4串,2串a,2串b


/*
@resouces: codeforces 551B
@date: 2017-3-3
@author: QuanQqqqq
@algorithm: greedy simulation 
*/
#include <bits/stdc++.h>

#define maxn 200005
using namespace std;

char ch1[maxn],ch2[maxn],ch3[maxn];
int num1[50],num2[50],num3[50],temp[50];


int main(){
    scanf("%s %s %s",ch1,ch2,ch3);
    int max1 = maxn,max2 = maxn,tt;
    int len1 = strlen(ch1);
    int len2 = strlen(ch2);
    int len3 = strlen(ch3);
    memset(num1,0,sizeof(num1));
    memset(num2,0,sizeof(num2));
    memset(num3,0,sizeof(num3));
    for(int i = 0;i < len1;i++){
        num1[ch1[i] - 'a']++;
    }
    for(int i = 0;i < len2;i++){
        num2[ch2[i] - 'a']++;   
    }
    for(int i = 0;i < len3;i++){
        num3[ch3[i] - 'a']++;
    }
    for(int i = 0;i < len2;i++){
        max1 = min(max1,num1[ch2[i] - 'a'] / num2[ch2[i] - 'a']);
    }
    for(int i = 0;i < len3;i++){
        max2 = min(max2,num1[ch3[i] - 'a'] / num3[ch3[i] - 'a']);
    }
    for(int i = 0;i < 26;i++){
        temp[i] = num1[i];
    }
    int sum = 0;
    if(max1 > max2){
        for(int i = max1;i >= 0;i--){
            for(int j = 0;j < 26;j++){
                num1[j] = temp[j];
            }
            for(int j = 0;j < len2;j++){
                num1[ch2[j] - 'a'] -= i;
            }
            tt = maxn;
            for(int j = 0;j < len3;j++){
                tt = min(tt,num1[ch3[j] - 'a'] / num3[ch3[j] - 'a']);
            }
            if(tt + i > sum){
                sum = tt + i;
                max1 = i;
                max2 = tt;
            }
        }
    } else {
        for(int i = max2;i >= 0;i--){
            for(int j = 0;j < 26;j++){
                num1[j] = temp[j];
            }
            for(int j = 0;j < len3;j++){
                num1[ch3[j] - 'a'] -= i;
            }
            tt = maxn;
            for(int j = 0;j < len2;j++){
                tt = min(tt,num1[ch2[j] - 'a'] / num2[ch2[j] - 'a']);
            }
            if(tt + i > sum){
                sum = tt + i;
                max2 = i;
                max1 = tt;
            }
        }
    }
    for(int i = 0;i < 26;i++){
        num1[i] = temp[i];
    }
    for(int i = 0;i < max1;i++){
        printf("%s",ch2);
    }
    for(int i = 0;i < len2;i++){
        num1[ch2[i] - 'a'] -= max1;
    }
    for(int i = 0;i < max2;i++){
        printf("%s",ch3);
    }
    for(int i = 0;i < len3;i++){
        num1[ch3[i] - 'a'] -= max2;
    }
    for(int i = 0;i < 26;i++){
        for(int j = 0;j < num1[i];j++)
            printf("%c",'a' + i);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值