L2-047 锦标赛 - java

题目解析

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

解题思路

模拟

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

然后在之后的每轮中,当前这场比赛的败者能力值 与 上一轮的相应两场比赛( $ 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;
	}

}


团体程序设计天梯赛-练习集-java

赞赏