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

题意:消消乐,每次必须消除数量大于等于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 << endl
const 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值