我的PAT系列文章更新重心已移至Github,歡迎來看PAT題解的小伙伴請到Github Pages瀏覽最新內容。此處文章目前已更新至與Github Pages同步。歡迎star我的repo。
題目
對于計算機而言,顏色不過是像素點對應的一個 24 位的數值。現給定一幅分辨率為
的畫,要求你找出萬綠叢中的一點紅,即有獨一無二顏色的那個像素點,并且該點的顏色與其周圍 8 個相鄰像素的顏色差充分大。
輸入格式:
輸入第一行給出三個正整數,分別是 和
(
1000),即圖像的分辨率;以及 TOL,是所求像素點與相鄰點的顏色差閾值,色差超過
TOL 的點才被考慮。隨后 行,每行給出
個像素的顏色值,范圍在
內。所有同行數字間用空格或 TAB 分開。
輸出格式:
在一行中按照 (x, y): color
的格式輸出所求像素點的位置以及顏色值,其中位置 x
和 y
分別是該像素在圖像矩陣中的列、行編號(從
1 開始編號)。如果這樣的點不唯一,則輸出 Not Unique
;如果這樣的點不存在,則輸出 Not Exist
。
輸入樣例 1:
8 6 200
0 0 0 0 0 0 0 0
65280 65280 65280 16711479 65280 65280 65280 65280
16711479 65280 65280 65280 16711680 65280 65280 65280
65280 65280 65280 65280 65280 65280 165280 165280
65280 65280 16777015 65280 65280 165280 65480 165280
16777215 16777215 16777215 16777215 16777215 16777215 16777215 16777215
輸出樣例 1:
(5, 3): 16711680
輸入樣例 2:
4 5 2
0 0 0 0
0 0 3 0
0 0 0 0
0 5 0 0
0 0 0 0
輸出樣例 2:
Not Unique
輸入樣例 3:
3 3 5
1 2 3
3 4 5
5 6 7
輸出樣例 3:
Not Exist
思路
在這道題上我好像想多了,當然也有可能陳越姥姥想少了(怎么可能,不可能的)。
首先就是,“顏色差” 是什么?網上其他人的做法99%(可能100%)都是直接把兩個顏色的值相減,結果的整數就是顏色差了。
而我參考了Wiki: Color difference,
將(R, G, B)三維顏色空間的“距離”作為顏色差,這也是很合理的。比如65280,也就是#00FF00,是綠色,
而65279,#00FEFF,是青色,兩者在整數大小上相差1,但是顏色有很大區別。幸好(或許也是不幸)在測試用例沒有使用上面這樣的例子,
我的測試結果和大家都是一樣的。
然后就是大家都遇到的難(keng)點:
- 第一個難(keng)點:
要求你找出萬綠叢中的一點紅,即有獨一無二顏色的那個像素點
解讀:需要這個顏色在整幅圖中只出現一次。
- 第二個難(keng)點:雖然題目說
該點的顏色與其周圍8個相鄰像素的顏色差充分大。
但是題目還是設置了處于邊界的滿足“條件”的點,所以說這又是一個題目敘述不清楚的案例(好多受害者)。
應對這個問題目前看到的代碼中有兩個解決方案,一是加入邊界特殊情況的檢測,二是在題目數據的周圍加一圈0。
第一個方案沒有問題。第二個方案我覺得是有問題的,如圖片的左上角有這樣的數據:
#000001 #0000FF ......
#0000FF #0000FF ......
...... ...... ......
假設顏色#000001在圖片只出現了這一次,這樣這個點應該符合要求。但是周圍加上0就變成了
#000000 #000000 #000000 ......
#000000 #000001 #0000FF ......
#000000 #0000FF #0000FF ......
...... ...... ...... ......
不管顏色差是怎么算的,這個中間的#000001
都是不能被檢測出來的。但是又很幸運地,我看使用這個方法的代碼也都通過了。
我能說什么呢 :)
P.S.
關于代碼優化:這個代碼運行時間好長(160+ms),應該是判斷顏色唯一太耗時了,相當于O(N2*M2),
或許改為用另一個排序好的列表查找會好很多(預計時間復雜度為M*N*log(M*N))。
更新:上面的判斷竟然是錯的,我在本地測試了上述方案,使用最多的數據1000*1000,排序加查找竟然比原來的方案耗時多一個數量級
~~~o(>﹏<)o。之前的方案從文件讀取用了0.2秒,但是查找只用了0.04秒(其中iUnique函數只有0.02秒!)。
新的方案qsort用了0.2秒,查找(使用了bsearch)用了0.3秒!這不科學 (ㄒoㄒ) (難道是被stdlib坑了?)
(證明瓶頸在數據讀取上,那運行時間長的鍋我就不背了)
代碼
最新代碼@github,歡迎交流
#include <stdio.h>
#define SQR(X) ((X)*(X))
#define R(COLOR) ((COLOR & 0XFF0000) >> 16)
#define G(COLOR) ((COLOR & 0X00FF00) >> 8)
#define B(COLOR) (COLOR & 0X0000FF)
#define D(C1, C2) (SQR(R(C1) - R(C2)) + SQR(G(C1) - G(C2)) + SQR(B(C1) - B(C2)))
int iUnique(int array[][1000], int x, int y, int x0, int y0)
{
for(int i = 0; i < x; i++)
for(int j = 0; j < y; j++)
if(array[i][j] == array[x0][y0] && !(i == x0 && j == y0))
return 0;
return 1;
}
int main()
{
int M, N, TOL;
scanf("%d %d %d", &M, &N, &TOL);
int fig[1000][1000];
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++)
scanf("%d", &fig[i][j]);
int count = 0, M0, N0;
for(int i = 0; i < N; i ++)
for (int j = 0; j < M; j++)
if((i > 0 && j > 0 ? D(fig[i][j], fig[i - 1][j - 1]) > SQR(TOL) : 1)
&& (i > 0 ? D(fig[i][j], fig[i - 1][j ]) > SQR(TOL) : 1)
&& (i > 0 && j < M ? D(fig[i][j], fig[i - 1][j + 1]) > SQR(TOL) : 1)
&& ( j > 0 ? D(fig[i][j], fig[i ][j - 1]) > SQR(TOL) : 1)
&& ( j < M ? D(fig[i][j], fig[i ][j + 1]) > SQR(TOL) : 1)
&& (i < N && j > 0 ? D(fig[i][j], fig[i + 1][j - 1]) > SQR(TOL) : 1)
&& (i < N ? D(fig[i][j], fig[i + 1][j ]) > SQR(TOL) : 1)
&& (i < N && j < M ? D(fig[i][j], fig[i + 1][j + 1]) > SQR(TOL) : 1)
&& iUnique(fig, N, M, i, j))
{
count++;
N0 = i;
M0 = j;
}
if(count == 0) printf("Not Exist");
if(count == 1) printf("(%d, %d): %d", M0 + 1, N0 + 1, fig[N0][M0]);
if(count >= 2) printf("Not Unique");
return 0;
}