戳这里:
//贪心的做法比较明显:取出方格中的数从左往右排列形成一个 m 进制的数,前者想要数最大,则每次取符合条件的最大的数,后者想要数最小,则每次取符合条件的最小的数。
//做法也比较暴力:在整个剩余的数形成的集合中两人每次贪心取数,那么就相当于是对剩余的数形成的集合进行搜索,考虑到极端情况:集合里面有很多数,但是只有一个可以取,这时通过加强集合元素的条件(是剩余的数 && (之前能被取出 || 现在能被取出))来缩小集合的大小,但是在数被取出之后需要对集合进行维护(添加元素)
//之前感觉写起来挺麻烦,就一直没动手去写,没想到今天写完交上去就过了......
1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 #include "utility" 6 #include "set" 7 #include "map" 8 using namespace std; 9 const int mod = 1e9 + 9;10 int m;11 int x[100010], y[100010];12 set s;13 map, int> mp;14 bool available(int index)15 {16 int X = x[index], Y = y[index];17 pair point = make_pair(X, Y), pre, next;18 bool no;19 int i, j;20 for(i = 1, pre = make_pair(X - 1, Y + 1); i <= 3; ++i, ++pre.first) {21 if(!mp[pre])22 continue;23 no = 1;24 for(j = 1, next = make_pair(pre.first - 1, pre.second - 1); j <= 3; ++j, ++next.first) {25 if(mp[next] && next != point) {26 no = 0;27 break;28 }29 }30 if(no)31 return 0;32 }33 return 1;34 }35 36 void res_add(__int64 &res, int v)37 {38 res = (res * m) % mod;39 res = (res + v) % mod;40 }41 42 void cube_add(int index)43 {44 int i;45 pair next;46 int tmp;47 for(i = 1, next = make_pair(x[index] - 1, y[index] - 1); i <= 3; ++i, ++next.first) {48 tmp = mp[next];49 if(!tmp)50 continue;51 --tmp;52 if(available(tmp)) {53 // printf("add_cube index == %d next == %d\n", index, tmp);54 // printf("%d %d\n", next.first, next.second);55 s.insert(tmp);56 }57 58 }59 }60 61 int main()62 {63 int i;64 scanf("%d", &m);65 for(i = 0; i <= m - 1; ++i) {66 scanf("%d%d", &x[i], &y[i]);67 mp[make_pair(x[i], y[i])] = i + 1;68 }69 for(i = 0; i <= m - 1; ++i) {70 if(available(i)) {71 s.insert(i);72 // printf("ava == %d\n", i);73 }74 }75 int tmp;76 __int64 res = 0;77 for(i = 1; i <= m; ++i) {78 while(!s.empty()) {79 if(i & 1)80 tmp = *s.rbegin();81 else82 tmp = *s.begin();83 // printf("chi == %d\n", tmp);84 s.erase(tmp);85 if(available(tmp)) {86 res_add(res, tmp);87 mp.erase(make_pair(x[tmp], y[tmp]));88 cube_add(tmp);89 break;90 }91 }92 }93 printf("%I64d\n", res);94 }