hdu 5440 Clock Adjusting(双向bfs)

来源:互联网 发布:装饰公司网络销售 编辑:程序博客网 时间:2024/06/05 20:56

题目链接:hdu 5440 Clock Adjusting

解题思路

卡着时间AC的,双向bfs,根据指向1,2…,12的clock个数建立hash函数,从终止状态逆向搜索5步,从起始状态正向搜索3步(因为终止状态对应的都是12,所以转移起来状态相对起始状态要少一些)

使用tool的顺序是无关紧要的,所以在搜索时,考虑到状态s,是通过使用前i个tool转移过来的,那么只需要在考虑使用i,i+1…,M即可(这里我优先使用编号大的tool,不确定有没有优化的作用)

在确定状态s和工具i后,需要枚举修改哪些clock,一开始我是用二进制状态表示需要被修改的地方,但是重复的太多,就用dfs+剪枝枚举。

这题应该还有更厉害的优化,我是卡1400Ms过的。

代码

#include <cstdio>#include <cstring>#include <set>#include <map>#include <vector>#include <queue>#include <algorithm>using namespace std;typedef long long ll;const int maxn = 1 * 1e5 + 5;ll S;int N, M, L[10], X[10], head, rear, ans;map<ll, int> C;set<ll> T;struct State {    ll s;    int f, c;    State(ll s = 0, int f = 0, int c = 0): s(s), f(f), c(c) {}}Q[maxn], cur;inline ll idx(int* c) {    ll ret = 0;    for (int i = 0; i < 12; i++)        ret = ret * (N+1) + c[i];    return ret;}inline void reidx(ll s, int* c) {    for (int i = 11; i >= 0; i--) {        c[i] = s % (N+1);        s /= (N+1);    }}void init () {    C.clear();    T.clear();    scanf("%d%d", &N, &M);    int x, cnt[15];    memset(cnt, 0, sizeof(cnt));    for (int i = 1; i <= N; i++) {        scanf("%d", &x);        if (x == 12) x = 0;        cnt[x]++;    }    S = idx(cnt);    for (int i = 0; i < M; i++)        scanf("%d%d", &L[i], &X[i]);}bool dfs1 (int d, int* c, int* t, int n, int m, int v) {    if (d > 12 || n > m) return false;    if (n == 0 && m == 0) {        ll tmp = idx(t);        if (tmp == S) {            ans = cur.c + 1;            return true;        }        if (!C.count(tmp)) {            C[tmp] = cur.c + 1;            if (cur.c < 4) Q[rear++] = State(tmp, v, cur.c+1);        }        return false;    }    for (int i = min(c[d], n); i >= 0; i--) {        if (n-i > m-c[d]) break;        t[(d-X[v]+12)%12] += i;        t[d] += (c[d] - i);        if (dfs1(d+1, c, t, n-i, m-c[d], v)) return true;        t[(d-X[v]+12)%12] -= i;        t[d] -= (c[d] - i);    }    return false;}bool dfs2 (int d, int* c, int* t, int n, int m, int v) {    if (d > 12 || n > m) return false;    if (n == 0 && m == 0) {        ll tmp = idx(t);        if (C.count(tmp)) {            ans = C[tmp] + cur.c + 1;            return true;        }        if (!T.count(tmp) && cur.c < 2) {            T.insert(tmp);            Q[rear++] = State(tmp, v, cur.c+1);        }        return false;    }    for (int i = min(c[d], n); i >= 0; i--) {        if (n-i > m-c[d]) break;        t[(d+X[v]+12)%12] += i;        t[d] += (c[d] - i);        if (dfs2(d+1, c, t, n-i, m-c[d], v)) return true;        t[(d+X[v]+12)%12] -= i;        t[d] -= (c[d] - i);    }    return false;}int bfs() {    int cnt[15], pos[15];    memset(cnt, 0, sizeof(cnt));    cnt[0] = N;    ll k = idx(cnt);    if (S == k) return 0;    C[k] = 0;    head = rear = 0;    for (int i = 0; i < M; i++) {        int x = (-X[i] + 12) % 12;        cnt[x] += L[i];        cnt[0] -= L[i];        ll tmp = idx(cnt);        if (!C.count(tmp)) {            if (tmp == S) return 1;            Q[rear++] = State(tmp, i, 1);            C[tmp] = 1;        }        cnt[x] -= L[i];        cnt[0] += L[i];    }    while (head < rear) {        cur = Q[head++];        reidx(cur.s, cnt);        for (int i = M-1; i >= cur.f; i--) {            memset(pos, 0, sizeof(pos));            if (dfs1(0, cnt, pos, L[i], N, i))                return ans;        }    }    head = rear = 0;    Q[rear++] = State(S, 0, 0);    while (head < rear) {        cur = Q[head++];        reidx(cur.s, cnt);        for (int i = M-1; i >= cur.f; i--) {            memset(pos, 0, sizeof(pos));            if (dfs2(0, cnt, pos, L[i], N, i)) return ans;        }    }    return -1;}int main () {    int cas;    scanf("%d", &cas);    while (cas--) {        init();        printf("%d\n", bfs());    }    return 0;}
0 0
原创粉丝点击