山東acm省賽(第六屆)Stars
阿新 • • 發佈:2018-11-05
這裡用尺取法
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StreamTokenizer; public class A { static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); public static int nextInt() throws IOException { in.nextToken(); return (int) in.nval; } public static String next() throws IOException { in.nextToken(); return (String) in.sval; } static int v[] = new int[405]; // 獲取一列的星星數量 static int n, k; public static void main(String[] args) throws Exception { int T = nextInt(); while(T-->0) { n = nextInt(); k = nextInt(); int a[][] = new int[n + 1][n + 1]; int x, y; for(int i = 0; i < n; i++) { x = nextInt(); y = nextInt(); a[x][y] = 1; } for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { a[i][j] += a[i][j - 1]; // 左邊的積累到右邊去、 } } for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { a[i][j] += a[i - 1][j]; // 上面的積累到下面去、、 } } int ans = n * n; // 兩額迴圈,遍歷所有的行(選兩行) for(int i = 0; i <= n; i++) { for(int j = i + 1; j <= n; j++) { ans = Math.min(ans, (j - i) * cal(a, i, j)); } } out.println(ans); out.flush(); } } public static int cal(int arr[][], int l, int r) { // 陣列,行座標,以及最少選幾個星星、 int start = 0, end = 0; // 起點終點, (尺取法) for(int i = 0; i <= n; i++) { v[i] = arr[r][i] - arr[l][i]; // 獲取一列的星星數量、、 } while(end <= n && v[end] < k) { end++; } if(end > n) { return 0x3f3f3f; // 返回一個很大的值,保證這個結果不會被選擇 } int ret = end; while(end <= n) { // 得出來的就是最小的範圍,且包含了至少k個星星 if(v[end] - v[start] >= k) { ret = Math.min(ret, end - start++); // 滿足的話,尾巴的就++ }else { end++; // 不滿足頭++ } } return ret; } }