在 R x C 的網格上,每一格可以租給一個用戶,當用戶之間共享一個邊時,將會增加不滿意程度,求租給 K 名用戶,建築的不滿意程度最低為何。
考慮 K 小的時候,將網格黑白染色,必然只放置在黑色或白色網格上,此時不滿意程度皆為 0。當 K 多餘白色格子或黑色格子時,將會增加不滿意程度,每當增加一格,勢必會挑選相對的顏色 (填滿白色格子後,選黑色格子來填),那麼每一次必須挑最少相鄰邊的格子。
為什麼一定會填滿其中一種顏色?假設最優解存在其中一種顏色未填滿,且存在這一格 x 附近沒有使用的格子,那麼必然存在將一個產生不滿意的格子移動到 x 會是一個更優解。不斷地迭代下去,就是貪心的來源!
[C. Hiking Deer]
跟蹤狂 H 在一個圓從 0 出發繞一圈,H 很討厭人群,因此盡可能不與其他人碰面,H 的能力可以跟蹤在任何人身後。現在知道一群人會不斷地繞著這個圓,並且分別以各自的速度、當前位置,全部人都按著順時針方式繞行,不存在兩個人在相同地點以相同速度。現在從 time = 0 開始,請問 H 至少會發生幾次碰面。
由於是一個環狀,又要考慮繞行的區間最少人數,朝著掃描線思路邁進!保證答案 (碰面次數) 不超過總人數 N,一開始瞬間移動到最快抵達終點的人身上,只會碰到 N - 1 個人!
根據抵達終點的時間排序,維護當前需要的碰面次數 e,假設尾隨編號 i 的人,需要碰面 e 個人!經過掃描一些人後,又遇到 i,表示 i 又繞了一圈,那麼碰面次數 e = e + 1,讓尾隨後面的點時,都會遇到那該死的 i!
A code
GCJ20151B - Counter Culture
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<stdio.h>
#include<string.h>
longlongreverseNumber(longlong x){
staticchar buf[32];
sprintf(buf, "%lld", x);
longlong y = 0;
for (int i = strlen(buf) - 1; i >= 0; i--)
y = y * 10 + buf[i] - '0';
return y;
}
longlongf(longlong n){
if (n < 10)
return n;
longlong half = 1;
while (half * half <= n)
half *= 10;
if (n % half == 0) // 1000 -> 999, 10000 -> 9999
return1 + f(n - 1);
else {
longlong v = reverseNumber(n - n%half + 1);
if (v != n - n%half + 1) // 123654 -> 100321, subtract & reverse
return n%half + f(v);
else// 19 -> 11, but 11 is palindrome, without reverse -> 10