HDU_2259
做这个题目首先要做Continuous Same Game(1),要不然不好测试对矩阵的操作是否是对的。
这个题目一开始怎么写怎么超时,如果改成用优先级队列的话就会爆空间,今天早晨才突然发现原来是对下面的这句话理解错了。
Then I will calculate the average of (Ai/Bi), 1<=i<=100. You will get WA if your ouput is invalid or this average is less than 1.5.
题目的意思是算100组case的Ai/Bi的平均值,并要求其不小于1.5,而我一开始理解成了每组case都要不小于1.5,这样很可能有些case本来就不存在比贪心策略更好的解法,从而导致了死循环。
因此这个题目可以随便搞个靠谱一点的贪心策略,然后用优先级队列搜几十步(具体多少步就要看实际情况了,如果MLE了就把步数改少点,如果WA了就把步数改大点)并取pop出的结果中的最优值输出即可。
#include<stdio.h> #include<string.h> #include<algorithm> #include<queue> #define MAXN 20 #define MAXD 210 #define MAXL 30 int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1}; int N, M, a[MAXN][MAXN]; void init() { int i, j; char b[MAXN]; for(i = N - 1; i >= 0; i --) { scanf("%s", b); for(j = 0; j < M; j ++) a[i][j] = b[j] - '0'; } } struct List { int x, y; }; struct St { int N, M, c, g[MAXN][MAXN], cnt[MAXD], col[MAXN][MAXN], A, L; int value; List list[MAXL]; bool operator < (const St &t) const { return value < t.value; } void init(int N, int M, int g[][MAXN]) { A = value = L = 0; this->N = N, this->M = M; memcpy(this->g, g, sizeof(this->g)); } inline int inside(int x, int y) { return x >= 0 && x < N && y >= 0 && y < M; } void color(int x, int y, int &cnt, int c) { int i, nx, ny; col[x][y] = c, ++ cnt; for(i = 0; i < 4; i ++) { nx = x + dx[i], ny = y + dy[i]; if(inside(nx, ny) && g[nx][ny] == g[x][y] && !col[nx][ny]) color(nx, ny, cnt, c); } } void erase(int x, int y) { int i, nx, ny; g[x][y] = 0; for(i = 0; i < 4; i ++) { nx = x + dx[i], ny = y + dy[i]; if(inside(nx, ny) && col[x][y] == col[nx][ny] && g[nx][ny]) erase(nx, ny); } } inline int find(int j) { for(int i = 0; i < N; i ++) if(g[i][j]) return 0; return 1; } void arrange() { int i, j, k, kmax; kmax = 0; for(j = 0; j < M; j ++) { k = 0; for(i = 0; i < N; i ++) if(g[i][j]) { if(i != k) g[k][j] = g[i][j], g[i][j] = 0; ++ k; } kmax = std::max(kmax, k); } N = kmax; k = 0; for(j = 0; j < M; j ++) if(!find(j)) { if(j != k) for(i = 0; i < N; i ++) g[i][k] = g[i][j]; ++ k; } M = k; } void deal() { int i, j; c = 0; for(i = 0; i < N; i ++) for(j = 0; j < M; j ++) col[i][j] = 0; for(i = N - 1; i >= 0; i --) for(j = 0; j < M; j ++) if(g[i][j] && !col[i][j]) { ++ c, cnt[c] = 0; color(i, j, cnt[c], c); if(cnt[c] == 1) col[i][j] = 0, -- c; } } void cal() { value = A; for(int i = 1; i <= c; i ++) if(cnt[i]) value += cnt[i] * (cnt[i] - 1); } }; void solve() { int i, j, cnt = 0, max, x, y; St ans; ans.init(N, M, a); ans.deal(), ans.cal(); std::priority_queue <St> q; q.push(ans); while(!q.empty()) { St st = q.top(); q.pop(); if(st.A > ans.A) ans = st; if(++ cnt >= 25) break; st.deal(); for(i = 0; i < st.N; i ++) for(j = 0; j < st.M; j ++) { int c = st.col[i][j]; if(c && st.cnt[c] > 1) { St nt = st; nt.erase(i, j), nt.arrange(); nt.A += st.cnt[c] * (st.cnt[c] - 1); nt.deal(), nt.cal(); nt.list[nt.L].x = i, nt.list[nt.L].y = j, ++ nt.L; q.push(nt); } st.cnt[c] = 0; } } printf("%d\n", ans.L); for(i = 0; i < ans.L; i ++) printf("%d %d\n", N - ans.list[i].x - 1, ans.list[i].y); } int main() { while(scanf("%d%d", &N, &M) == 2) { init(); solve(); } return 0; }