hdu4090 双重dfs模拟 + 启发式搜索

来源:互联网 发布:诺基亚衰落的原因知乎 编辑:程序博客网 时间:2024/06/07 06:49

题意:消消乐,每次必须消除数量大于等于3个,而且得分是消除个数的平方,每次消除之后局面往左下角收拢.
分析:
- 首先很容易想到对每个当前局面枚举每种颜色来dfs消除,注意这里对每一个已经消除过度页面要vis记录
要不然超时,比赛的时候记录了,但是初始化vis的地方写错了,导致TLE,交换了顺序就AC….看来代码逻辑还是
不够清晰,不能完整表达正确的想法,而且出现了错误不能很快正确的debug.
- 对当前局面消除了之后,用类似unique函数的实现方式,模拟处理之后的局面再进行搜索,所以这里是两层
dfs嵌套.
- 这里的一个核心剪枝是启发式剪枝,假设当前局面的最优结果来和答案比较.
Get:
代码能力很重要,平时要正确一次AC的能力.

/************************************************ *Author        :jibancanyang *Created Time  :2016年05月04日 星期三 15时55分49秒 ***********************************************/#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <cmath>#include <cstdlib>#include <ctime>#include <stack>using namespace std;typedef pair<int, int> pii;typedef long long ll;typedef unsigned long long ull;vector<int> vi;#define xx first#define yy second#define lowbit(x) (x&-x)#define sa(n) scanf("%d", &(n))#define rep(i, a, n) for (int i = a; i < n; i++)#define vep(c) for(decltype((c).begin() ) it = (c).begin(); it != (c).end(); it++) #define pr(x) cout << #x << " " << x << " "#define prln(x) cout << #x << " " << x << endlconst int mod = int(1e9) + 7, INF = 0x3f3f3f3f, maxn = 1e5 + 12;int dirx[] = {-1, -1, 0, 1, 1, 1, 0, -1};int diry[] = {0, 1, 1, 1, 0, -1, -1, -1};int co[7];int G[9][9];int n, m, k, ans, cnt;bool vis[9][9];void pt(void) {    prln(ans);    cout << "co: " << endl;    rep (i, 1, k + 1) cout << i << ": " << co[i]  << " " ;    cout << endl;    cout << "G: " << endl;    rep (i, 1, n + 1) {        rep (j , 1, m + 1) {            cout << G[i][j] << " ";        }        cout << endl;    }}int dfs1(int x, int y, int c) {    int ret = 1;    vis[x][y] = true;    G[x][y] = -1;    rep (i, 0, 8) {        int u = x + dirx[i], v = y + diry[i];        if (u > 0 && u <= n && v > 0 && v <= m && !vis[u][v] && G[u][v] == c) {            ret += dfs1(u, v, c);        }    }    return ret;}void pre(void) {    int ed = 1;    int GG[9][9];    rep (i, 1, n + 1) rep (j, 1, m + 1) GG[i][j] = -1;    for (int i = 1; i <= m; i++) {        int st = n;        bool ok = false;        for (int j = n; j > 0; j--) {            if (G[j][i] != -1) ok = true, GG[st--][ed] = G[j][i];        }        if (ok) ed++;    }    memcpy(G, GG, sizeof(G));}void dfs(int p) {    int temp = 0;    rep (i, 1, k + 1) if (co[i] >= 3) temp += co[i] * co[i];    ans = max(ans, p);    if (temp + p <= ans) return;    memset(vis, 0, sizeof(vis));    rep (i, 1, k + 1) {        if (co[i] >= 3) {            rep (a, 1, n + 1) {                rep (b, 1, m + 1) {                    if (G[a][b] == i && !vis[a][b]) {                        int Gtemp[9][9];                        memcpy(Gtemp, G, sizeof(G));                        bool sd[9][9];                        int kk = dfs1(a, b, i);                        memcpy(sd, vis, sizeof(vis));                        co[i] -= kk;                        if (kk >= 3)  pre(), dfs(p + kk * kk);                        co[i] += kk;                        memcpy(vis, sd, sizeof(vis));                        memcpy(G, Gtemp, sizeof(G));                    }                }            }        }    }}int main(void){#ifdef LOCAL    freopen("in.txt", "r", stdin);    //freopen("out.txt", "w", stdout);#endif    while (~scanf("%d%d%d", &n, &m, &k) ) {       // if (T++) break;        ans = 0;        memset(co, 0, sizeof(co));        rep (i, 1, n + 1)            rep (j, 1, m + 1)             sa(G[i][j]), co[G[i][j]]++;        dfs(0);        printf("%d\n", ans);    }    return 0;}
0 0