L2-030 冰岛人 - java

题目解析

给定n个人的姓名,求m组人名的关系。

题目保证不存在两个人是同名的。

孩子的姓等于父亲的名加后缀。

解题思路

在输入n个人的姓名时,通过姓的性别后缀来判断是否为 维京人后裔

  • 后缀为ssonsdottir,则为维京人后裔
  • 后缀为 mf,则为其他人
    -- ssonm,表示男
    -- sdottirf,表示女

然后用名来存储,每个人的性别与姓


然后再判断m组人名的时候
先判断两个人是否都出现在名单中

  • 未出现, 则输出NA
  • 出现,则判断两个人性别是否相同
    • 相同, 则输出 Whatever
      • 最后判断两个人是否五代内有公共祖先
        • 出现,则输出No
        • 未出现, 则输出Yes

如何判断两个人是否五代以内呢?

  • 因为孩子的姓等于父亲的名
  • 所以可以通过判断当前这个人的姓往上找祖先

注: 本题我java过不去,最后一个数据怎么都是TLE

代码

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

public class Main
{
	static TreeMap<String, edge> tr = new TreeMap<String, edge>();

	static String check(String a, String b)
	{
		int cnt1 = 0; // a的第几代祖先了
		while (!a.equals("")) // 如果a还有祖先
		{
			int cnt2 = 0; // b的第几代祖先了
			String c = b; // b的第0代祖先为自己
			while (!c.equals("")) // 如果b还有祖先
			{
			    // 如果a的祖先与b的祖先相同,并且在5代以内
				if (a.equals(c) && (cnt1 < 4 || cnt2 < 4)) return "No";
				// 如果当前判断的a祖先与b祖先都超过了5代
				if (cnt1 >= 4 && cnt2 >= 4) return "Yes";
				c = tr.get(c).fname; // 替换b的祖先
				cnt2++; // b的祖先代数增加
			}
			a = tr.get(a).fname; // 替换a的祖先
			cnt1++; // a的祖先代数增加
		}
		return "Yes";
	}

	public static void main(String[] args)
	{
		int n = sc.nextInt();
		while (n-- > 0)
		{
			String sname = sc.next(); // 名
			String fname = sc.next(); // 姓

            // 姓的长度
			int len = fname.length();
			// 姓中的带性别后缀
			char op = fname.charAt(len - 1);
			
			// 如果是维京人后裔的男
			if (op == 'n') tr.put(sname, new edge(1, fname.substring(0, len - 4)));
			// 如果是维京人后裔的女
			else if (op == 'r') tr.put(sname, new edge(0, fname.substring(0, len - 7)));
			// 如果是其他人的男
			else if (op == 'm') tr.put(sname, new edge(1, ""));
			// 如果是其他人的女
			else if (op == 'f') tr.put(sname, new edge(0, ""));
		}

		int m = sc.nextInt();
		while (m-- > 0)
		{
			String sname1 = sc.next();
			String fname1 = sc.next();
			String sname2 = sc.next();
			String fname2 = sc.next();
			// 判断两个人是否有一个人不在名单内
			if (!tr.containsKey(sname1) || !tr.containsKey(sname2)) out.println("NA");
			// 判断两个人是否同性
			else if (tr.get(sname1).sex == tr.get(sname2).sex) out.println("Whatever");
			else out.println(check(sname1, sname2));
		}

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

	static class edge
	{
		int sex; // 性别
		String fname; // 姓(也就是父亲的名)

		public edge(int sex, String fname)
		{
			this.sex = sex;
			this.fname = fname;
		}
	}

	static Scanner sc = new Scanner(System.in);
	static PrintWriter out = new PrintWriter(System.out);

}

c++

#include <iostream>
#include <unordered_map>

#define PIS pair<int, string>

using namespace std;

const int N = 1e5 + 10;
unordered_map<string, PIS> mp;

string check(string a, string b)
{
    int cnt1 = 0;
    while(a != "")
    {
        int cnt2 = 0;
        string c = b;
        while(c != "")
        {
            if(a == c && (cnt1 < 4 || cnt2 < 4)) return "No";
            if(cnt1 >= 4 && cnt2 >= 4) return "Yes";
            c = mp[c].second;
            cnt2 ++;
        }
        a = mp[a].second;
        cnt1 ++;
    }
    return "Yes";
}

int main()
{
    int n; cin >> n;
    while(n -- > 0)
    {
        string a, b; cin >> a >> b;
        if(b.back() == 'n') mp[a] = {1, b.substr(0, b.size() - 4)};
        else if(b.back() == 'r') mp[a] = {0, b.substr(0, b.size() - 7)};
        else if(b.back() == 'm') mp[a] = {1, ""};
        else if(b.back() == 'f') mp[a] = {0, ""};
    }
    
    int m; cin >> m;
    while(m -- > 0)
    {
        string a, b, c, d; cin >> a >> b >> c >> d;
        if(!mp.count(a) || !mp.count(c)) cout << "NA\n";
        else if(mp[a].first == mp[c].first) cout << "Whatever\n";
        else cout << check(a, c) << "\n";
    }
    
    return 0;
}

TreeMap
TreeMap


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

赞赏