练习题 William's Colored Pencils

完整题目描述:

William received N colored pencils as a present. Each pencil’s color is a combination of red, green and blue. The color of the ith colored pencil can be denoted with 3 integers, Ri, Gi, Bi , and they mean red, green and blue element in order. The difference between the colors of the ith colored pencil and the jth colored pencil can be expressed as follows.

MAX(|Ri - Rj|, |Gi - Gj|, |Bi - Bj|)

The colorfulness of a bundle of colored pencils can be calculated with the biggest difference in colors among the pencils included in the bundle. Willian wants to minimize the colorfulness by using only K colored pencils out of N colored pencils he was presented with. Why don’t you help William? In this case, K colored pencils are selected out of N colored pencils on a random basis and William must use K colored pencils.   [Input] The first line contains a single integer Tㅡthe number of total test cases. The first line of each test case contains N and K. (2 ≤ K ≤ N ≤ 100000) From the 2nd line through N line of each test case contain the information on the ith colored pencil, Ri, Gi, Bi, and they are separated by a space. (0 ≤ (Ri, Gi, Bi) ≤ 255)

[Output] For each test case, print the minimum colorfulness on the 1st line. From the next line through K line, print the information on the colored pencils that created the corresponding colorfulness. If there are several answers, you can print any of those answers.

 

Input Example

4 // T : Number of test case

2 2 // N : Number of Total Pencils, K : Number of Pencils to use

1 3 2 // R1, G1, B1

2 6 4

3 2

3 3 4 // 2nd test case’s N, K

1 6 4

1 1 2

5 3 6

6 4 // 3rd test case’s N, K

6 2 7

3 1 3

4 1 5

6 2 6

4 3

1 1 1 // 4rd test case’s N, K

2 2 2

9 9 9

10 10 10

 

Output Example

#1 3

1 3 2

2 6 4

#2 2

1 1 2

3 3 4

#3 2

4 1 5

6 2 7

6 2 6

#4 8

2 2 2

9 9 9

10 10 10  

 

In the 1st test case, the answer is MAX(|R2 – R1|, |G2 – G1|, |B2 – B1|) = 3. 

 

题解:求三维坐标空间中两点的最小距离,距离定义是最远的那一维的坐标值。

从小向大设定棱长Length,遍历所有棱长为Length的立方体,看能否找到一个立方体,其中包含K个点。

如果能找到,则Length为所求。

 

 1 /*William's_Colored_Pencils
 2 题意:每支铅笔有RGB三种颜色,(0 ≤ (Ri, Gi, Bi) ≤ 255),从N支铅笔中取出差异最小的K支。差异表达式:MAX(|Ri - Rj|, |Gi - Gj|, |Bi - Bj|) (2 ≤ K ≤ N ≤ 100000)*/
 3 #include <stdio.h>
 4 int T, N, K, sx, sy, sz, cnt, map[MAX][MAX][MAX], num[MAX][MAX][MAX];
 5 bool findK(int len){//遍历所有棱长为len的立方体,能找到K个点返回true
 6     for (i = len; i < MAX; ++i)
 7     for (j = len; j < MAX; ++j)
 8     for (k = len; k < MAX; ++k){ //求立方体内包含的点,从第一个终止点开始遍历
 9         int tmp = num[i][j][k]
10             -num[i-len][j][k]-num[i][j-len][k]-num[i][j][k-len]
11             +num[i-len][j-len][k]+num[i-len][j][k-len]+num[i][j-len][k-len]
12             -num[i-len][j-len][k-len];    
13         if (tmp >= K){
14             sx = i; sy = j; sz = k;
15             cnt = len; 
16             return true;
17         }
18     }
19     return false;
20 }
21 int main(void){
22     scanf("%d", &T);
23     for (int test_case = 1; test_case <= T; test_case++){
24         scanf("%d%d", &N, &K);
25         for (i = 0; i < MAX; ++i)
26         for (j = 0; j < MAX; ++j)
27         for (k = 0; k < MAX; ++k){
28             map[i][j][k] = 0;
29         }
30         for (int t = 0; t < N; ++t){
31             scanf("%d%d%d", &i, &j, &k); //i,j,k顺序不确定,先得到map数组
32             ++map[i + 1][j + 1][k + 1]; //为了相减运算不出现num[-1],平移立方体
33         }
34         for (i = 1; i < MAX; ++i)
35         for (j = 1; j < MAX; ++j)
36         for (k = 1; k < MAX; ++k){ //得到小于等于数组,从原点到该点之间包含的所有点
37             num[i][j][k] = map[i][j][k]
38                 +num[i-1][j][k]+num[i][j-1][k]+num[i][j][k-1]
39                 -num[i][j-1][k-1]-num[i-1][j][k-1]-num[i-1][j-1][k]
40                 +num[i-1][j-1][k-1];
41         }
42         int left = 1, right = MAX, mid;
43         while (left < right){ //二分查找,最多查找8次
44             mid = (left + right) / 2;
45             if (findK(mid)) right = mid;
46             else left = mid + 1;
47         }
48         printf("#%d %d\n", test_case, cnt - 1); //其实cnt=left
49         for (i = sx - cnt + 1; i <= sx; i++)
50         for (j = sy - cnt + 1; j <= sy; j++)
51         for (k = sz - cnt + 1; k <= sz; k++)
52         while (map[i][j][k] && K){
53             --map[i][j][k];
54             --K;
55             printf("%d %d %d\n", i - 1, j - 1, k - 1);
56         }
57     }
58     return 0;
59 }

 

posted @ 2017-12-28 16:56  proscientist  阅读(180)  评论(0编辑  收藏  举报