算法訓練 審美課(Java)

題目鏈接:http://lx.lanqiao.cn/problem.page?gpid=T519

問題描述

《審美的歷程》課上有n位學生,帥老師展示了m幅畫,其中有些是梵高的作品,另外的都出自五歲小朋友之手。老師請同學們分辨哪些畫的作者是梵高,但是老師自己並沒有答案,因爲這些畫看上去都像是小朋友畫的……老師只想知道,有多少對同學給出的答案完全相反,這樣他就可以用這個數據去揭穿披着皇帝新衣的抽象藝術了(支持帥老師_)。
  答案完全相反是指對每一幅畫的判斷都相反。

輸入格式

第一行兩個數n和m,表示學生數和圖畫數;
  接下來是一個n*m的01矩陣A:
  如果aij=0,表示學生i覺得第j幅畫是小朋友畫的;
  如果aij=1,表示學生i覺得第j幅畫是梵高畫的。

輸出格式

輸出一個數ans:表示有多少對同學的答案完全相反。

樣例輸入

3 2
1 0
0 1
1 0

樣例輸出

2

樣例說明

同學1和同學2的答案完全相反;
  同學2和同學3的答案完全相反;
  所以答案是2。

數據規模和約定

對於50%的數據:n<=1000;
  對於80%的數據:n<=10000;
  對於100%的數據:n<=50000,m<=20。

首先自己採用暴力破解的方法寫的,只得了50分,後面的超時。然後開始參考大佬的方法
大佬1:https://blog.csdn.net/weixin_42474261/article/details/87736683
將輸入的0,1數據可看爲二進制數,每一個二進制對應一個獨一的十進制,這樣我們把每一個同學的判斷作爲一個數,然後將該數作爲一個新數組的下標,這樣只要有同學的判斷是相同的,則他們二進制數對應的十進制數也是相同的,同理下標也是相同的,所以下標相同時,下標對應的值加一。
這樣我們就對輸入輸入處理完了。然後開始找判斷完全相反的同學的對數。利用異或這一位運算“^”,如果兩個同學的判斷完全相反,則兩位同學的二進制數異或後爲1。利用這一結論,我們來找同學對數。
首先找到m個1對應十進制數,用來和同學的十進制數異或運算,得到的數,作爲下標,在統計次數的數組中找到對應的值,相加。這樣逐個類推下去,可統計到所有的。
然而改了之後,只得了60分,還時超時。
大佬2:https://blog.csdn.net/qq_42794545/article/details/87939021
題目輸入數據很大,需要用字符流來讀寫數據。不然會超時
改了輸入的方式後,就過了,100分

代碼如下:

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

public class Main {
	private static Reader reader;
	public static void main(String[] args) {
//		Scanner sc = new Scanner(System.in);
//		int n = sc.nextInt();
//		int m = sc.nextInt();
		reader = new InputStreamReader(System.in);
		int n = getInt();
		int m = getInt();
		int[] ind = new int[50001];
		int[] res = new int[2000000];
		int sum = 0;
		for(int i=0;i<n;i++) {
			int[] mrr = new int[21];
			for(int j=0;j<m;j++) {
				mrr[j] = getInt();
			}
			ind[i] = toDec(mrr, m);
			res[ind[i]]++;
		}
		int max = toSum(m);
		for(int i=0;i<n;i++) {
			int tmp = ind[i] ^ max;
			sum += res[tmp];
		}
		System.out.println(sum/2);
//		Scanner sc = new Scanner(System.in);
//		int[][] view = new int[50000][22];
//		String[] str0 = new String[50001];
//		String[] str1 = new String[50001];
//		int n = sc.nextInt();
//		int m = sc.nextInt();
//		int sum = 0;
//		for(int i=0;i<n;i++) {
//			for(int j=0;j<m;j++) {
//				view[i][j] = sc.nextInt();
//			}
//		}
//		for(int i=0;i<n;i++) {
//			str0[i] = toStr0(view[i], m);
//			str1[i] = toStr1(view[i], m);
//		}
//		for(int i=0;i<n;i++) {
//			for(int j=i+1;j<n;j++) {
//				if(str0[i].equals(str1[j]))
//					sum ++; 
//			}
//		}
//		System.out.println(sum);
	}
	public static int getInt() {
		int res = 0, read;
		try {
			while ((read = reader.read()) != -1) {
				if (Character.isDigit(read)) {// 因爲全是非負數,不需要判斷負號‘-’,只要是數字就行
					res = read - '0';
					while ((read = reader.read()) != -1) {// 繼續得到能得到的數字
						if (Character.isDigit(read)) {
							res = res * 10 + (read - '0');
							} else {
								break;
		}
						}
					break;
		}
				}
			} catch (IOException e) {
				e.printStackTrace();
				}
		return res;
		}
	public static int toDec(int[] arr, int m) {
		int sum = 0;
		int time = 1;
		for(int i=m-1;i>=0;i--) {
			sum += arr[i] * time;
			time *= 2;
		}
		return sum;
	}
	public static int toSum(int m) {
		int sum = 0;
		int time = 1;
		while(m!=0) {
			sum += time;
			time *= 2;
			m--;
		}
		return sum;
	}
//	public static String toStr0(int[] arr, int m) {
//		StringBuilder sb = new StringBuilder();
//		for (int i = 0; i < m; i++) {
//			sb.append(arr[i]);
//		}
//		return sb.toString();
//	}
//	public static String toStr1(int[] arr, int m) {
//		StringBuilder sb = new StringBuilder();
//		for(int i=0;i<m;i++) {
//			if(arr[i] == 0)
//				sb.append(1);
//			else
//				sb.append(0);
//		}
//		return sb.toString();
//	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章