AcWing 4736. 步行者 c++和Java实现

18 篇文章 0 订阅
17 篇文章 0 订阅

题目

约翰参加了一场步行比赛。

比赛为期 N 天,参赛者共 M 人(包括约翰)。

参赛者编号为 1∼M,其中约翰的编号为 P。

每个参赛者的每日步数都将被赛事方记录并公布。

每日步数最多的参赛者是当日的日冠军(可以有并列冠军)。

如果一名参赛者可以连续 N 天成为日冠军,那么他将成为创造历史的传奇冠军,这正是约翰的最终目标。

在比赛结束后,约翰拿到了所有选手的全部成绩,并试图分析自己在实现目标方面还差了多少步。

对于第 i 天,如果约翰是当日的冠军,那么他就会对当日的发挥表示满意,即当日不需要额外多走步数,如果约翰不是当日的冠军,那么他就会计算当日若要夺冠,还需要额外走的最小步数。

请你计算并输出,为了实现目标,约翰在这 N 天中需要额外走的最小总步数。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。

每组数据第一行包含三个整数 M,N,P。

接下来 M 行,每行包含 N 个整数,其中第 i 行第 j 个数 Si,j 表示第 i 个参赛者第 j 天的行走步数。

输出格式
每组数据输出一个结果,每个结果占一行。

结果表示为 Case #x: y,其中 x 为组别编号(从 1 开始),y 为实现目标需要额外走的最小总步数。

数据范围
1≤T≤100,
2≤M≤1000,
1≤N≤31,
1≤P≤M,
1≤Si,j≤60000

输入样例1:

1
2 3 1
1000 2000 3000
1500 1500 3000

输出样例1:

Case #1: 500

样例1解释
在此样例中,比赛为期 3 天,共 2 人参赛,约翰是 1 号选手。

第 1 天,约翰若想夺冠,至少还需额外走 500 步。

后两天,约翰均为日冠军,无需额外多走步数。

所以,他一共需要额外走 500 步。

输入样例2:

2
3 2 3
1000 2000
1500 4000
500 4000
3 3 2
1000 2000 1000
1500 2000 1000
500 4000 1500

输出样例2:

Case #1: 1000
Case #2: 2500

样例2解释
在 Case 1 中,比赛为期 2 天,共 3 人参赛,约翰是 3 号选手。

第 1 天,约翰若想夺冠,至少还需额外走 1000 步。

第 2 天,约翰为日冠军,无需额外多走步数。

所以,他一共需要额外走 1000 步。

在 Case 2 中,比赛为期 3 天,共 3 人参赛,约翰是 2 号选手。

第 1 天,约翰为日冠军,无需额外多走步数。

第 2 天,约翰若想夺冠,至少还需额外走 2000 步。

第 3 天,约翰若想夺冠,至少还需额外走 500 步。

所以,他一共需要额外走 2500 步。

解题思路

题目要求求出每天约翰与冠军步数差距的总和。

所以我们需要求出每天冠军的步数,并记录约翰每天的步数。

我们可以用数组 sp 来记录约翰每天的步数。

使用 max 或者 top 数组来求每天冠军的步数,其中 max[j] 或 top[j] 代表第 j + 1 天步数最大值。只需要在读取第 i 位参赛选手第 j + 1 天的步数,和 max[j] 或 top[j] 进行比较留最大值即可。

最后遍历 N 天,求出第 j + 1 天约翰和冠军步数的距离,即 max[j] - sp[j] 或 top[j] - sp[j],并进行求和即可。

AC代码

Java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class Main {
	
	public static void main(String[] args) throws IOException {
		InputReader in = new InputReader(System.in);
		PrintWriter out = new PrintWriter(System.out);
		
		int t = in.nextInt();
		
		int m = 0;
		int n = 0;
		int p = 0;
		
		int s = 0;
		int[] sp;
		int[] max;
		
		int res = 0;
		
		for(int k = 1; k <= t; k++) {
			m = in.nextInt();
			n = in.nextInt();
			p = in.nextInt();
			
			sp = new int[n];
			max = new int[n];
			
			for(int i = 0; i < m; i++) {
				for(int j = 0; j < n; j++) {
					s = in.nextInt();
					max[j] = Math.max(max[j], s);
					if(i + 1 == p) sp[j] = s;
				}
			}
			
			res = 0;
			
			for(int i = 0; i < n; i++) res += max[i] - sp[i];
			
			out.println("Case #" + k + ": " + res);
		}
		
		out.flush();
	}

	public static class InputReader {
		BufferedReader reader;
		StringTokenizer tokenizer;
		
		public InputReader(InputStream in) {
			reader = new BufferedReader(new InputStreamReader(in));
		}
		
		public String next() throws IOException {
			while(tokenizer == null || !tokenizer.hasMoreTokens()) {
				tokenizer = new StringTokenizer(reader.readLine());
			}
			
			return tokenizer.nextToken();
		}
		
		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}
	}
}

c++

#include<bits/stdc++.h>

using namespace std;

const int N = 32;

int main()
{
    int t = 0;
    scanf("%d", &t);

    int m = 0;
    int n = 0;
    int p = 0;

    int s = 0;

    int top[N];
    int sp[N];

    int res = 0;

    for(int k = 1; k <= t; k++)
    {
        scanf("%d%d%d", &m, &n, &p);

        memset(top, 0, sizeof(top));
        memset(sp, 0, sizeof(sp));

        for(int i = 0; i < m; i++)
        {
            for(int j = 0; j < n; j++)
            {
                scanf("%d", &s);
                top[j] = max(top[j], s);
                if(i + 1 == p) sp[j] = s;
            }
        }

        res = 0;
        for(int i = 0; i < n; i++) res += top[i] - sp[i];

        printf("Case #%d: %d\n", k, res);
    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值