เฉลยโจทย์ hyperhackathon ครั้งที่ 2

เนื่องจาก ในวันที่ 25 พฤษภาคม 2557 ที่ผ่ามมา มีการแข่งขัน เขียนโปรแกรม hyperhackathon ที่โรงแรม Swissôtel Le Concorde รัชดา ผมจึงขอเฉลยโจทย์ Part แรก ในส่วนของ Algorithm ครับ ไม่ถูกต้องยังไง บอกกล่าวได้นะครับ http://www.hyperhackathon.com/

โจทย์ชุดที่ 1



เวลาในการแข่งขัน 1 ชั่วโมง 45 นาที
โจทย์มีทั้งหมด 5 ข้อ รวมคะแนนทั้งหมด 80 คะแนน
สามารถเลือกทำโจทย์ข้อใดก่อนก็ได้ ไม่จำเป็นต้องเรียงตามลำดับ
สามารถเขียนโปรแกรมด้วยภาษาใดก็ได้


ข้อ 1.1 - 1.2

1.1 จงหาจำนวนเฉพาะที่น้อยที่สุดแต่มากกว่า 1,000,000 (1 คะแนน)

1.2 จงหาจำนวนเฉพาะที่น้อยที่สุดแต่มากกว่า x (3 คะแนน)
ผู้ให้คะแนนจะกำหนด x ซึ่งเป็นจำนวนเต็ม ไม่เกิน 7 หลัก ให้ทั้งหมด 3 ครั้ง คำตอบที่ถูกต้องจะได้คำตอบละ 1 คะแนน

for(int i=2;i< MAX_NUM ; i ++)
{
	boolean isPrime = true;
	for(int j=0;j< prime.size() ; j ++)
	{
		if(i % prime.get(j) == 0)
		{
			isPrime= false;
			break;
		}
	}
	if(isPrime)
	{
		prime.add(i);
	}
}


idea คือ หาจำนวนเฉพาะเก็บไว้เยอะๆก่อน แล้วตอน รันจริงก็มาหาจากใน list นี้

n! เป็นสัญลักษณ์แทนค่า factorial ของ n ซึ่งเท่ากับ n x (n-1) x (n-2) x ... x 1 เช่น
5! = 5 x 4 x 3 x 2 x 1 = 120
10! = 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1 = 3,628,800
ผลรวมของเลขโดดทุกตัวของ 5! คือ 1+2+0 = 3
ผลรวมของเลขโดดทุกตัวของ 10! คือ 3+6+2+8+8+0+0 = 27


ข้อ 1.3 - 1.4



1.3 จงหาผลรวมของเลขโดดทุกตัวของ 10,000! (1 คะแนน)

1.4 จงหาผลรวมของเลขโดดทุกตัวของ n! (3 คะแนน)
ผู้ให้คะแนนจะกำหนด n ซึ่งเป็นจำนวนเต็ม ไม่เกิน7 หลัก ให้ทั้งหมด 3 จำนวน คำตอบที่ถูกต้องจะได้คำตอบละ 1 คะแนน



int n = INPUT;
BigInteger x = BigInteger.ONE;
for (int i = 1; i <= n; i++)
{
	x = x.multiply(new BigInteger("" + i));
}
String s = x.toString(10);
int sum = 0;
for (int i = 0; i < s.length(); i++)
{
	int xx =  (int)(s.charAt(i)-48);
	sum += xx;
}
System.out.println(sum);


ข้อนี้คือ ต้องรู้จักกับการจัดการเลขเยอะๆ ที่ใส่ใน int กับ long ไม่พอ ถ้าใช้ python ก็จะได้เปรียบกว่าคนอื่นนิดหน่อย

ข้อ 2.1-2.2

2.1 มีคำกล่าวว่า เลขคู่ ทุกๆตัวที่มากกว่าหรือเท่ากับ 4 สามารถเขียนได้ในรูปของจำนวนเฉพาะ (Prime number) 2 ตัวบวกกัน เช่น
4 = 2 + 2
6 = 3 + 3
14 = 11 + 3
ยังไม่มีมนุษย์คนไหนสามารถพิสูจน์ได้ว่า คำกล่าวนี้เป็นจริง


เราจะทำการทดลองว่าเลขคู่ที่สุ่มขึ้นมานั้นสามารถหาจำนวนเฉพาะ 2 ตัวที่มีผลรวมเท่ากับตัวมันเองได้หรือไม่ เมื่อรับค่าเลขคู่ ให้โปรแกรมตอบเป็นจำนวนเฉพาะ 2 ตัว หรือ “Sorry” หากไม่มีจำนวนเฉพาะเหล่านั้นอยู่จริง (6 คะแนน)

ในบางกรณี เลขคู่ มีคู่ของจำนวนเฉพาะ มากกว่า 1 คู่ เช่น 14 = 7 + 7 และ 14 = 3+ 11 สามารถตอบกรณีใดก็ได้

ผู้ให้คะแนนจะกำหนดเลขคู่ ไม่เกิน 7 หลัก ทั้งหมด 3 จำนวน คำตอบที่ถูกต้องจะได้คำตอบละ 2 คะแนน

ข้อนี้เอา list ของจำนวนเฉพาะ แบบข้อแรกก่อนแล้วก็ check ใน list อีกทีครับ

for (int j = 0; j < prime.size(); j++)
{
	int k = prime.get(j);
	if (prime.contains(n - k))
	{
		System.out.println(n + " = " + k + "+" + (n - k));
		return;
	}
}
System.out.println("Sorry !!!!!");






2.2 จงเขียนโปรแกรมรับค่า n ซึ่งเป็นจำนวนเต็มบวก ไม่เกิน 2 หลัก และให้โปรแกรมแสดงผลดังนี้ (4 คะแนน)



n=3

--x--
-x-x-
x-x-x
-x-x-
--x--

n=4

---x---
--x-x--
-x---x-
x--x--x
-x---x-
--x-x--
---x---

n=5

----x----
---x-x---
--x---x--
-x-----x-
x---x---x
-x-----x-
--x---x--
---x-x---
----x----
ข้อนี้ยังไงก็ขอไม่เฉลยแล้วกันครับ น่าจะได้กันอยู่แล้ว

ข้อ 3

ในตารางจตุรัส 20 x 20 ด้านล่าง

34 90 61 34 10 42 01 90 54 69 20 50 58 70 58 42 48 82 73 84
20 43 78 99 49 30 15 70 41 27 61 36 96 66 44 78 58 76 79 05
76 39 32 74 28 16 90 88 37 94 47 51 78 04 17 61 65 39 35 05
36 01 64 17 37 55 90 39 12 39 71 78 77 25 09 36 20 67 44 06
72 06 78 03 62 28 99 87 39 65 44 07 24 72 04 50 46 51 83 35
57 39 22 39 17 92 44 59 24 36 81 66 87 13 57 87 55 14 15 91
83 25 10 22 35 13 69 24 47 49 48 78 14 23 56 39 24 45 49 05
19 95 97 39 82 73 66 33 01 80 98 30 44 11 56 39 51 00 41 73
41 07 36 88 74 65 88 26 12 29 16 16 87 94 25 10 27 44 18 34
00 06 06 46 93 53 84 93 87 92 57 42 74 44 11 30 50 69 65 53
34 52 89 81 48 98 53 13 91 35 15 43 26 05 19 30 32 00 12 01
86 27 93 90 26 52 84 73 65 04 33 99 50 34 79 32 27 54 69 86
95 82 36 96 75 15 68 17 28 35 46 15 49 54 68 07 29 42 56 85
53 60 22 29 26 78 87 60 37 73 35 57 91 60 49 64 29 23 87 94
75 07 72 03 82 79 83 62 06 06 93 35 93 31 63 65 56 72 60 62
97 51 78 55 65 06 43 29 53 08 90 46 80 96 71 55 75 45 74 76
39 15 27 39 67 23 30 96 10 08 75 06 67 02 16 40 67 76 97 80
15 11 73 19 70 95 64 16 00 30 00 16 59 31 77 18 40 86 98 98
05 32 40 25 12 26 00 68 64 23 59 40 29 30 42 11 26 22 80 38
36 77 48 18 62 50 00 85 67 72 39 93 03 17 26 38 89 96 86 68

มีเลข 4 ตัวตามแนวทะแยงมุม ซึ่งแสดงด้วยตัวหนาและขีดเส้นใต้ ผลรวมของเลข 4 ตัวนั้นคือ
52 + 68 + 60 + 06 = 186

จงหาผลรวมที่มากที่สุด และน้อยที่สุด ของเลขที่ติดกัน 4 ตัวตามแนวใดก็ได้ (ขึ้น, ลง, ซ้าย, ขวา, ทะแยงซ้าย, ทะแยงขวา) แต่จะต้องติดกันเท่านั้น จากตารางที่กำหนดให้

ผู้ให้คะแนนจะให้ไฟล์ .TXT บรรจุข้อมูลสำหรับทดสอบ จำนวน 12 Test case โดยมีข้อมูลดังนี้
a) บรรทัดแรก จะเป็นตัวเลข m ซึ่งคือขนาดของตารางของ Test case เช่น 15 หมายถึงตารางมีขนาด 15 x 15 (ตารางเป็นจตุรัสเท่านั้น)
b) บรรทัดต่อไป m บรรทัด จะเป็นข้อมูลตัวเลขภายในตารางของ Test case

และบรรทัดต่อไปจะตามด้วยข้อมูล a) และ b) ของ Test case ต่อๆไป ภายในไฟล์เดียวกัน จนครบ 12 Test case คำตอบที่ถูกต้องจะได้คะแนน Test case ละ 1 คะแนน

testcase ข้อ 3-5 สามารถ load ได้จาก
https://expert-programming-tutor.com/tutorial/fitwhey2_testcase.7z


Scanner sc = new Scanner(new File("grid/grid_x_" + testcase_count + ".txt"));
			PrintWriter pw = new PrintWriter(new File("grid/grid_x_out_" + testcase_count + ".txt"));
			int T = sc.nextInt();
			sc.nextLine();

			for (int innerCase = 0; innerCase < T; innerCase++)
			{
				int N = sc.nextInt();
				sc.nextLine();
				int[][] g = new int[N][N];
				int i = 0;
				while (sc.hasNext() && i < N)
				{
					String s = sc.nextLine();
					String ss[] = s.split(" ");
					for (int j = 0; j < N; j++)
					{
						g[i][j] = Integer.parseInt(ss[j]);
					}

					i++;
				}
				
				
				
				 System.out.println(52 + 68 + 60 + 06);
				int max = 0;
				int min = Integer.MAX_VALUE;
				for (i = 0; i < N; i++)
				{
					for (int j = 0; j < N - 3; j++)
					{
						int n = g[i][j] + g[i][j + 1] + g[i][j + 2] + g[i][j + 3];
						if (n > max)
						{
							max = n;
						}
						if (n < min)
						{
							min = n;
						}
					}
				}

				for (int j = 0; j < N; j++)
				{
					for (i = 0; i < N - 3; i++)
					{

						int n = g[i][j] + g[i + 1][j] + g[i + 2][j] + g[i + 3][j];
						if (n > max)
						{
							max = n;
						}
						if (n < min)
						{
							min = n;
						}
					}
				}

				for (int j = 0; j < N - 3; j++)
				{
					for (i = 0; i < N - 3; i++)
					{

						int n = g[i][j] + g[i + 1][j + 1] + g[i + 2][j + 2] + g[i + 3][j + 3];
						if (n > max)
						{
							max = n;
						}
						if (n < min)
						{
							min = n;
						}
					}
				}

				for (int j = 3; j < N; j++)
				{
					for (i = 0; i < N - 3; i++)
					{

						int n = g[i][j] + g[i + 1][j - 1] + g[i + 2][j - 2] + g[i + 3][j - 3];
						if (n > max)
						{
							max = n;
						}
						if (n < min)
						{
							min = n;
						}
					}
				}

				System.out.print("max = " + max + "\t");
				System.out.println("min = " + min);

				
				pw.println("testcase " + (innerCase + 1) + " : " + "max = " + max + "\t" + "min = " + min);
			}
			pw.close();
			sc.close();


ขอนี้จริงๆไม่มีอะไร เชื่อว่าถ้ามีเวลาเยอะกว่านี้หลายๆคนทำได้แน่นอนครับ จริงๆ ในงานพลาดนิดนึ่งที่ไม่ได้บอกว่า TESTCASE จะใหญ่แค่ไหน


ข้อ 4



สมชายได้รับมรดกเป็นที่ดิน (ที่นา) จากบิดา ซึ่งเป็นชาวนาและมีอาชีพเสริมคือนักคณิตศาสตร์ ปัญหาคือว่า นาที่นี่ไม่ได้แบ่งคันนาเหลี่ยมๆ เหมือนที่อื่นๆ นาที่นี่มีลักษณะดังนี้


xxxxxxxxxxxxxxxxxxxx
x       x x        x
x       x x        x
x       x x        x
x    xxxx x        x
x    x    xxxxxxxxxx
x    x    x        x
x    x    x        x
x    xxxxxxxxxxxxxxx
x    x     x       x
x  xxx     x       x
xxxx       x       x
x          x       x
xxxxxxxxxxxxxxxxxxxx


ตัว x แทนคันนา และพื้นที่ว่างๆ สามารถปลูกข้าวได้
คุณต้องการหาว่า ในที่นาแต่ละที่จะมีกี่"ห้อง"กันแน่ (ห้องคือ บริเวณภายในที่นาที่ถูกแบ่งโดยคันนา )
และเนื่องจากว่าพ่อของคุณเป็นคนรวยจึงมีที่นาเยอะมาก ดังนั้นคุณจึงตัดสินใจที่จะเขียนโปรแกรมเพื่อหาจำนวน "ห้อง" ในที่นาแต่ละแปลง และนอกจากนี้คุณยังอยากรู้ว่า ที่นาแต่ละแปลงมีห้องที่ใหญ่ที่สุดใหญ่แค่ไหน
นิยามของการติดกันคือ พื้นที่ว่า ต้องติดกันแบบ บน, ล่าง ,ซ้าย, ขวา เท่านั้น ตามแนวทะแยงไม่ถือว่าติดกัน

ตัวอย่าง 1 ตามรูปภาพด้านบนที่ให้มา
มี 6 ห้อง และ ห้องที่ใหญ่ที่สุดคือ 47
xxxxxxxxxxxxxxxxxxxx
x       x x        x
x       x x        x
x       x x    32  x
x    xxxx x        x
x 47 x    xxxxxxxxxx
x    x 16 x  16    x
x    x    x        x
x    xxxxxxxxxxxxxxx
x    x     x       x
x  xxx     x       x
xxxx   27  x  28   x
x          x       x
xxxxxxxxxxxxxxxxxxxx

ตัวอย่าง 2
xxxxxxxxxx
x   x  x x
x   x  x x
x   x  x x
x        x
xxxxxxxxxx

มี 1 ห้อง ขนาดใหญ่ สุด คือ 26


input บรรทัดแรกคือจำนวน Test Case t โดยที่ t เป็นจำนวนเต็ม
ซึ่ง 1 <= t <= 1000
บรรทัดต่อๆไปจะเป็น test case อีก t test case ซึ่งแต่ละ test case จะประกอบด้วย
บรรทัดแรกของแต่ละ test case จะมี ค่า integer 2 ตัว คือ m กับ n โดยที่
1 <= m<= 1000 และ 1 <= n<= 1000
และตามด้วย อีก n บรรทัด แต่ละบรรทัดมี m ตัวอักษร ตัวอักษร x (x เล็ก)แทนคันนา space bar (' ') แทน พื้นที่ว่าง
output ให้บันทึกผลลง file ตั้งชื่อ ตามชื่อของตัวเอง เช่น ถ้าท่านผู้เข้าแข่งขันชื่อ สมชาย ใจดี ให้ตั้งชื่อfile ว่า somchai_jaidee_part_1_6.txt
โดยมี format ดังนี้
case i : num max
โดย i คือ case ที่(เริ่มจาก 1)
num คือ จำนวนห้อง
max คือ ขนาดของห้องที่ใหญ่ที่สุด


ตัวอย่าง
2
14 20
xxxxxxxxxxxxxxxxxxxx
x       x x        x
x       x x        x
x       x x        x
x    xxxx x        x
x    x    xxxxxxxxxx
x    x    x        x
x    x    x        x
x    xxxxxxxxxxxxxxx
x    x     x       x
x  xxx     x       x
xxxx       x       x
x          x       x
xxxxxxxxxxxxxxxxxxxx
5 5
xxxxx
x   x
x xxx
x x x
xxxxx

ตอบ
case 1 : 6 47
case 2 : 2 5

เช่นกันข้อนี้พลาดตรงที่ไม่ได้บอกให้ชัดเจนว่า input ใหญ่ได้แค่ไหน



วิธีการคือ Breadth First Search หรือ Depth First Search ก็ได้





import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class mazeSolver
{

	public static void main(String[] args) throws FileNotFoundException
	{
		for (int count_x = 1; count_x <= 4; count_x++)
		{
			int number_test = count_x;
			PrintWriter pw = new PrintWriter(new File("maze/maze_" + number_test + "_out.txt"));
			ArrayList<Integer[][]> allInput = readFile("maze/maze_" + number_test + ".txt");
			for (int i = 0; i < allInput.size(); i++)
			{
				int result[] = new int[2];
				solver(allInput.get(i), result);
				System.out.println("number_test "+
				number_test+"num = " + result[0] + " max = " + result[1]);
				pw.println("case " + (i + 1) + " : " + "num = " + result[0] + " max = " + result[1]);
			}
			pw.close();
		}
	}

	public static void solver(Integer[][] maze, int[] result)
	{
		ArrayList<Integer> countList = new ArrayList<Integer>();
		for (int i = 0; i < maze.length; i++)
		{
			for (int j = 0; j < maze[i].length; j++)
			{
				if (maze[i][j] == 0)
				{
					int r = countRoomSize(maze, new MazePoint(j, i), countList.size() + 1);
					countList.add(r);
				}
			}
		}

		int max = 0;
		for (int i = 0; i < countList.size(); i++)
		{
			if (countList.get(i) > max)
			{
				max = countList.get(i);
			}
		}
		result[0] = countList.size();
		result[1] = max;

	}

	public static int countRoomSize(Integer[][] maze, MazePoint start, int num)
	{
		int count = 0;
		Queue<MazePoint> q = new LinkedList<MazePoint>();
		q.add(start);

		while (q.size() > 0)
		{
			MazePoint p = q.poll();
			count++;
			maze[p.y][p.x] = num;

			if (p.y > 0 && maze[p.y - 1][p.x] == 0)
			{
				q.add(new MazePoint(p.x, p.y - 1));
				maze[p.y - 1][p.x] = -100;
			}

			if (p.x > 0 && maze[p.y][p.x - 1] == 0)
			{
				q.add(new MazePoint(p.x - 1, p.y));
				maze[p.y][p.x - 1] = -100;
			}

			if (p.x < maze[0].length - 1 && maze[p.y][p.x + 1] == 0)
			{
				q.add(new MazePoint(p.x + 1, p.y));
				maze[p.y][p.x + 1] = -100;
			}

			if (p.y < maze.length - 1 && maze[p.y + 1][p.x] == 0)
			{
				q.add(new MazePoint(p.x, p.y + 1));
				maze[p.y + 1][p.x] = -100;
			}
		}
		return count;
	}

	public static ArrayList<Integer[][]> readFile(String path) throws FileNotFoundException
	{
		Scanner sc = new Scanner(new File(path));
		ArrayList<Integer[][]> allInput = new ArrayList<Integer[][]>();
		sc.nextLine();
		for (; sc.hasNext();)
		{
			int n = sc.nextInt();
			int m = sc.nextInt();
			sc.nextLine();
			Integer[][] maze = new Integer[n][m];

			for (int i = 0; i < n; i++)
			{
				String l = sc.nextLine();
				for (int j = 0; j < m; j++)
				{
					if (l.charAt(j) == 'x')
						maze[i][j] = -1;
					else
						maze[i][j] = 0;
				}
			}
			allInput.add(maze);
		}

		sc.close();
		return allInput;
	}
}

class MazePoint
{
	public int x, y;

	public MazePoint()
	{
	}

	public MazePoint(int xx, int yy)
	{
		x = xx;
		y = yy;
	}
}




คุณนัทมีแมวอยู่ n ตัว แต่ละตัวมีหมายเลขกำกับไม่ซ้ำกัน ติดอยู่บนปลอกคอของแมว หมายเลขไม่จำเป็นต้องเรียงกัน เช่น มีแมว 3 ตัว แมวมีหมายเลข 6, 700 ,15 ซึ่งหมายเลขนั้นจะแสดงความดุของแมว เช่น หมายเลข 5 แปลว่า แมวตัวนี้จะข่วน 5 ครั้งสำหรับการไปจับหรือยุ่งด้วย 1 รอบ หมายเลข 600 แปลว่าแมวตัวนี้จะข่วน 600 ครั้งต่อการไปจับหรือยุ่งด้วย 1 รอบ

แมวทั้ง n ตัวของคุณนัทมาเข้าแถวเพื่อรอกินอาหารเย็น (เป็นแมวที่เรียบร้อยมากๆ?) คุณนัทเป็นคนเรื่องมากเรื่องการให้อาหารแมว โดยจะให้อาหารแมวแบบตามลำดับหมายเลขจากน้อยไปหามากเสมอ คุณนัทจึงต้องอุ้มแมว 2 ตัวให้สลับที่กัน แต่การอุ้มแมว คุณนัทต้องโดนแมวข่วนตามหมายเลขที่อยู่บนตัวแมว เช่น แมวมาเข้าแถวรอกินข้าวดังนี้

1 , 11 , 7 , 8 , 6

เพื่อให้หมายเลขของแมวเรียงจากน้อยไปมาก คุณนัทจะสลับแมวหมายเลข 6 กับ 11 จึงจะได้

1 , 6 , 7 , 8 , 11

และคุณนัทจะโดนแมวหมายเลข 6 และ 11 ข่วน 6 + 11 = 17 ครั้ง ซึ่งเจ็บมาก



คุณนัทมีแมวเป็นจำนวนมากจึงได้ขอให้ท่านเขียนโปรแกรมเพื่อช่วยให้เขาเจ็บตัวน้อยที่สุด

กรุณาเขียนโปรแกรมช่วยเรียงหมายเลขแมวจากน้อยไปหามาก โดยใช้วิธีการสลับแมว 2 ตัวใดๆ เพื่อให้คุณนัทโดนแมวข่วนน้อยที่สุด และเพื่อให้คุณนัทตื่นเต้น กรุณาตอบผลลัพธ์เพียงจำนวนครั้งที่คุณนัทจะโดนข่วน



โปรแกรมจะรับข้อมูลเข้า 2 บรรทัด

บรรทัดแรกคือ จำนวนแมว

บรรทัดที่ 2 คือ หมายเลขที่ปลอกคอแมวแต่ละตัว ที่มาเข้าแถวรอทานข้าว โดยคั่นด้วยช่องว่าง





Input output
3
3 2 1
4
4
8 1 2 4
17


ผู้ให้คะแนนจะให้ไฟล์ .TXT บรรจุข้อมูลสำหรับทดสอบ จำนวน 25 ชุด โดยเป็นข้อมูลบรรทัดแรก (จำนวนแมว) และบรรทัดที่ 2 (หมายเลขที่ปลอกคอแมวแต่ละตัว) สลับกันไปจนครบ 25 ชุด คำตอบที่ถูกต้อง จะได้คะแนนชุดละ 1 คะแนน

ตอนนี้ง่วงขี้เกียจอธิบาย เอาเป็นว่าใช้ greedy ครับ แล้วก็มี if else เพิ่มอีกนิดหน่อบ แต่ตามนี้เลย





			int a[];
			int b[];
			boolean visited[];
			int T;
			int t = 0;
			// Scanner sc = new Scanner(new File("sillysort_in.txt"));
			// PrintWriter out = new PrintWriter(new File("sillysort_out.txt"));
			//

			Scanner sc = new Scanner(new File("cat/in_" + count_x + ".txt"));
			PrintWriter out = new PrintWriter(new File("cat/out_" + count_x + ".txt"));
			T = sc.nextInt();
			sc.nextLine();
			for (t = 1; t <= T; t++)
			{
				int N = sc.nextInt();
				sc.nextLine();
				a = new int[N];
				b = new int[N];
				visited = new boolean[N];

				String s = sc.nextLine();
				String ss[] = s.split(" ");

				for (int i = 0; i < N; i++)
				{
					a[i] = Integer.parseInt(ss[i]);
					b[i] = a[i];
					visited[i] = false;
				}

				Arrays.sort(b);
				HashMap<Integer, Integer> place = new HashMap<Integer, Integer>();

				for (int i = 0; i < N; ++i)
				{
					place.put(b[i], i);
				}

				int res = 0;
				for (int i = 0; i < N; ++i)
				{
					if (visited[i] == false)
					{
						if (place.get(a[i]) == i)
						{
							visited[i] = true;
							continue;
						}
						// 
						int min_val = a[i];
						int num = 0;
						int sum = 0;
						int j = i;

						while (visited[j] == false)
						{
							sum += a[j];
							num++;
							if (a[j] < min_val)
							{
								min_val = a[j];
							}
							visited[j] = true;
							j = place.get(a[j]);
						}
						sum -= min_val;
						res += sum + min_val * (num - 1);

						if (2 * (b[0] + min_val) < (min_val - b[0]) * (num - 1))
						{
							res -= (min_val - b[0]) * (num - 1) - 2 * (b[0] + min_val);
						}
					}
				}
				out.printf("Case %d: %d\n", t, res);

			}

			out.close();
			sc.close();




ปล. ข้อนี้เหมือนจะ copy code นี้มาจากใครสักคน ขอบคุณมากและกัน