L2-047 锦标赛 - java

L2-047 锦标赛


Java (javac)
时间限制
1200 ms
内存限制
512 MB
其他编译器
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB


题目描述:

2 k 2^{k} 2k名选手将要参加一场锦标赛。锦标赛共有 k k k 轮,其中第 i i i 轮的比赛共有 2 k − i 2^{k-i} 2ki 场,每场比赛恰有两名选手参加并从中产生一名胜者。每场比赛的安排如下:

  • 对于第 1 1 1 轮的第 j j j 场比赛,由第 ( 2 j − 1 ) (2j − 1) (2j1) 名选手对抗第 2 j 2j 2j 名选手。
  • 对于第 i i i 轮的第 j j j 场比赛 ( i > 1 ) (i > 1) (i>1),由第 ( i − 1 ) (i − 1) (i1) 轮第 ( 2 j − 1 ) (2j − 1) (2j1) 场比赛的胜者对抗第 ( i − 1 ) (i − 1) (i1) 轮第 2 j 2j 2j 场比赛的胜者。

k k k 轮唯一一场比赛的胜者就是整个锦标赛的最终胜者。
举个例子,假如共有 8 8 8 名选手参加锦标赛,则比赛的安排如下:

  • 1 1 1 轮共 4 4 4 场比赛:选手 1 1 1 vs 选手 2 2 2,选手 3 3 3 vs 选手 4 4 4,选手 5 5 5 vs 选手 6 6 6,选手 7 7 7 vs 选手 8 8 8
  • 2 2 2 轮共 2 2 2 场比赛:第 1 1 1 轮第 1 1 1 场的胜者 vs 第 1 1 1 轮第 2 2 2 场的胜者,第 1 1 1 轮第 3 3 3 场的胜者 vs 第 1 1 1 轮第 4 4 4 场的胜者。
  • 3 3 3 轮共 1 1 1 场比赛:第 2 2 2 轮第 1 1 1 场的胜者 vs 第 2 2 2 轮第 2 2 2 场的胜者。

已知每一名选手都有一个能力值,其中第 i i i 名选手的能力值为 a i a_{i} ai 。在一场比赛中,若两名选手的能力值不同,则能力值较大的选手一定会打败能力值较小的选手;若两名选手的能力值相同,则两名选手都有可能成为胜者。

l i , j l_{i,j} li,j 表示第 i i i 轮第 j j j 场比赛 败者 的能力值,令 w w w 表示整个锦标赛最终胜者的能力值。给定所有满足 1 ≤ i ≤ k 1 \le i \le k 1ik 1 ≤ j ≤ 2 k − i 1 \le j \le 2^{k-i} 1j2ki l i , j l_{i,j} li,j 以及 w w w,请还原出 a 1 , a 2 , ⋯   , a n a_{1}, a_{2}, \cdots, a_{n} a1,a2,,an

输入格式:
第一行输入一个整数 k ( 1 ≤ k ≤ 18 ) k (1 \le k \le 18) k(1k18)表示锦标赛的轮数。
对于接下来 k k k 行,第 i i i 行输入 2 k − i 2^{k-i} 2ki 个整数 l i , 1 , l i , 2 , ⋯   , l i , 2 k − i l_{i,1}, l_{i, 2}, \cdots, l_{i,2^{k-i}} li,1,li,2,,li,2ki ,其中 l i , j l_{i,j} li,j 表示第 i i i 轮第 j j j 场比赛 败者 的能力值。
接下来一行输入一个整数 w ( 1 ≤ w ≤ 1 0 9 ) w (1 \le w \le 10^{9}) w(1w109)表示锦标赛最终胜者的能力值。

输出格式:
输出一行 n 个由单个空格分隔的整数 a 1 , a 2 , ⋯   , a n a_{1}, a_{2}, \cdots, a_{n} a1,a2,,an ,其中 a i a_{i} ai 表示第 i 名选手的能力值。如果有多种合法答案,请输出任意一种。如果无法还原出能够满足输入数据的答案,输出一行 No Solution
请勿在行末输出多余空格。

输入样例1:
3
4 5 8 5
7 6
8
9
输出样例1:
7 4 8 5 9 8 6 5

输入样例2:
2
5 8
3
9
输出样例2:
No Solution

提示:
本题返回结果若为格式错误均可视为答案错误


给定k轮比赛中,每场比赛失败者的能力值。
求每个人的能力值


emmmmmmm

模拟

在第一轮比赛的到败者的时候,可以先将前者视作为败者,然后将后者视作为胜者。

然后在之后的每轮中,当前这场比赛的败者能力值 与 上一轮的相应两场比赛(j << 1 与 j << 1 | 1) 的败者能力值 相比

  • 都小于,则无法还原
  • 大于等于其中一个,则胜者为另一个
  • 都大于等于,则随意选一个为胜者

需要注意一点的是:会出现上一轮比赛的败者能力值比这轮败者能力值大的情况。所以需要将上一轮败者的最大能力值更新为本轮败者能力值中。


import java.io.*;
import java.math.*;
import java.util.*;

public class Main
{

	public static void main(String[] args) throws IOException
	{
		int k = ini();

		int lost[][] = new int[k + 1][1 << k]; // 存储第i轮j场中的败者的能力值
		int win[][] = new int[k + 1][1 << k]; // 存储第i轮j场中的胜者
		int ans[] = new int[1 << k]; // 存储每个人的能力值

        boolean f = false; // 是否不能还原每个人的能力值
		for (int i = 1; i <= k; i++)
		{
			for (int j = 0; j < (1 << k - i); j++)
			{
				lost[i][j] = ini();

				// 统一前者为败者 后者为胜者
				if (i == 1)
				{
					ans[j << 1] = lost[i][j];
					win[i][j] = j << 1 | 1;
					continue;
				}

				// 如果当前败者的能力值,比上一轮的两个败者的能力值低,则无法还原所有人的能力值
				if (lost[i][j] < lost[i - 1][j << 1] && lost[i][j] < lost[i - 1][j << 1 | 1])
				    f = true;
				
                // 如果当前败者的能力值 大于等于 上一轮败者中前者的能力值
				if (lost[i][j] >= lost[i - 1][j << 1])
				{
					win[i][j] = win[i - 1][j << 1 | 1]; // 当前这轮的胜者为 上一轮败者中的后者
					ans[win[i - 1][j << 1]] = lost[i][j]; // 那么上一轮胜者的前者能力值为当前能力值
				} 
				else
				{
					win[i][j] = win[i - 1][j << 1]; // 当前这轮的胜者为 上一轮败者中的前者
					ans[win[i - 1][j << 1 | 1]] = lost[i][j]; // 那么上一轮胜者的后者能力值为当前能力值
				}
                // 将当前败者的能力值替换为最大的败者能力值
				lost[i][j] = Math.max(lost[i][j], Math.max(lost[i - 1][j << 1], lost[i - 1][j << 1 | 1]));
			}
		}

		int w = ini();
        // 如果胜者的能力值比第k轮的败者能力值低,则无法还原
		if (w < lost[k][0])
		    f = true;
		   
		
		if(f) out.println("No Solution"); // 不能还原
		else
		{
    		ans[win[k][0]] = w; // 存入冠军的能力值
    		
            // 输出所有人的能力值
    		for (int i = 0; i < (1 << k); i++)
    		{
    			if (i != 0) out.print(" ");
    			out.print(ans[i]);
    		}
		}

		out.flush();
		out.close();
	}

	static StreamTokenizer sc = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(System.out);

	static int ini() throws IOException
	{
		sc.nextToken();
		return (int) sc.nval;
	}

}


如果有说错的 或者 不懂的 尽管提 嘻嘻

一起进步!!!


闪现

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谢谢 啊sir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值