算法训练#17:试着模拟一下——Running for Gold和Maximum Cost Deletion

15 阅读2分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 20 天,点击查看活动详情

第一题

Running for Gold

题目理解

有若干个被选中的运动员参与了5场马拉松,给出他们的排名,然后给出比较运动员的成绩优劣的依据:若运动员甲在5场比赛中至少有3场的名次高于运动员乙,那么甲就优于乙。题目要求我们找出成绩能优于其他被选中的运动员的那个运动员

输入

输入整数tt,代表案例个数,1t1031\le t\le 10^{3}
每个案例第1行输入1个整数nn1n5×1041\le n\le 5\times 10^{4}
每个案例的第二行到第n+1n+1行输入5个整数:表示这若干个运动员参加这五场比赛所获得的名次

输出

每个案例输出一个整数——代表找出的最优的运动员(找不到最优者则输出-1)

思路代码

一般的模拟思路,就是用一个运动员作为“擂主”逐个去与其他运动员比较,不是最优者则换一个“擂主”,这样做的话最坏的情况下每个运动员都得当一次“擂主”,时间复杂度很高,会出现超时。要对模拟方法进行优化,那就要知道这个思路其实是分两步的,一步是找“擂主”,下一步是与其他人相比较。我们其实可以在找“擂主”上简单一点:先定一个人为“擂主”,若有优于这个人的则换更优者当擂主,这样若存在真正的最优者,最后的“擂主”一定会是他,但未必所有的赢到最后的人就是最优者,所以要再把“擂主”与其他人比较确认一遍。

import java.util.Scanner;

public class Run_for_gold {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();//读取输入
        for (int i = 0; i < t; i++) {
            int n=sc.nextInt();
            int[][] r=new int[n][5];
            for(int j=0;j<n;j++) {
                for (int k=0;k<5;k++) {
                    r[j][k]=sc.nextInt();//读取输入
                }
            }
            if(n==1) {//特殊情况:“无敌是多么寂寞”
                System.out.println(1);
                continue;
            }
            
            int zf=0;
            int best=0;
            //找出“擂主”
            for(int j=0;j<n;j++) {
                for (int k = 0; k < 5; k++) {
                    if(r[j][k]<r[best][k])
                        zf++;
                    else if(r[j][k]>r[best][k])
                        zf--;
                }
                if(zf>0)
                    best=j;
                zf=0;
            }
            //确认“擂主”是不是最优者
            int superior=0;
            for(int j=0;j<n;j++) {
                    for (int k = 0; k < 5; k++) {
                        if(r[j][k]<r[best][k])
                            zf++;
                        else if(r[j][k]>r[best][k])
                            zf--;
                    }
                    if(zf>0)
                        superior--;
                    else if(zf<0)
                        superior++;
                    zf=0;
            }
            int ans=-1;
            if(superior==n-1) {
                ans = best + 1;
            }
            System.out.println(ans);
        }
    }
}

第二题

Maximum Cost Deletion

题目理解

image.png 给出一个长度为nn的只含有0或者1的字符串ss,以及两个参数aabb,给出前提如下:

  1. 要把这个字符串里面的所有字符都删除
  2. 对删除操作有限制,每一次删除只能删除若干(这个可以自己定)个相同的字符(比如删除11100
  3. 删除一个长度为ll的字符串就会得到a×l+ba\times l+b
  4. 求出要达到要求所能得到的最多分数

输入

输入整数tt,代表案例个数,1t1031\le t\le 10^{3}
每个案例第1行输入1个整数nn1n100,100a,b1001\le n\le 100,-100\le a,b\le 100
每个案例的第二行输入一个长度为nn的字符串

输出

每个案例输出一个整数——代表能得到的最高分

思路

通过对删除过程以及删除操作的模拟我们发现:在不同的删除操作次数的情况下,参数aa对于得分情况的影响是相同的,而参数bb对得分的影响则很大。若参数bb为正,则删除次数肯定是越多越好,为负则反之。那么我们现在就只需要考虑如何使删除次数达到最少。要达到最少的话那就需要一次尽可能删除足够多的字符,那么我们这里可以稍微用一下贪心的思想:若把0或者1的其中一类全删了,然后再用一次删掉另一类,这是不是最少的呢?起码在测试了多种样例之后确实如此。

import java.util.Scanner;

public class Maximum_Cost_Deletion {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        for (int i = 0; i < t; i++) {
            int n=sc.nextInt();
            int a=sc.nextInt();
            int b=sc.nextInt();
            String s=sc.next();
            if(b>=0)
            {
                System.out.println(n*(a+b));
            }
            else {
                char[] x=s.toCharArray();
                char temp='x';//随便定个不是‘0’或‘1’的字符
                int count0=0;
                int count1=0;
                for(int j=0;j<n;j++)//找出0和1的段数
                {
                    if(x[j]!=temp&&x[j]=='1')
                    {
                        temp=x[j];
                        count1++;
                    }
                    else if(x[j]!=temp&&x[j]=='0')
                    {
                        temp=x[j];
                        count0++;
                    }
                }
                int count=count0>count1?count1:count0;
                int ans=(count+1)*b+n*a;
                System.out.println(ans);
            }

        }
    }
}