Jzoj P1496 页___bfs+哈希

题目大意:

给出序列 A A ,设其的升序序列为 B B ,每次可以进行的操作有两种:
①将当前序列的中位数放在队首
②将当前序列的中位数放在队尾
问序列 A A 转化成序列 B B 的最少转化次数,如若无法转化,则输出 No N o Answer A n s w e r

N N 只取 3579 3 、 5 、 7 、 9 四个数字中的一个
数的大小为 160190 160 到 190 之间的整数

分析:

跟USACO一道叫做魔板的题目很相似,
我们可以通过广搜去搜索它变化的状态,
通过hash判断状态的重复,
然后就没了,
因为我的hash表是以邻接表形式储存的,一开始邻接表的数组开的比较小。。
所以就很尴尬了

代码:

#include
#include
#include
#include
#include
#define modn 10007
#define M 500005
#define N 15

using namespace std;

typedef long long ll;

int Hash[M][N], Nxt[M], Ls[modn], d1[N], d2[N], a[N], b[N], n, cnt = 0;

void Init(int x) {
    d1[1] = x / 2 + 1;
    for (int i = 2; i <= x / 2 + 1; i++) d1[i] = i - 1;
    for (int i = x / 2 + 2; i <= x; i++) d1[i] = i;

    d2[x] = x / 2 + 1;
    for (int i = x - 1; i >= x / 2 + 1; i--) d2[i] = i + 1;
    for (int i = x / 2; i >= 1; i--) d2[i] = i;
}

int Get_hash(int *x) {
    int hash_num = 1;
    for (int i = 1; i <= n; i++)
         hash_num = (hash_num * x[i] + x[i]) % modn;
    return hash_num % modn;
}

bool Check(int *x) {
    bool flag;
    int rp = Get_hash(x);
    for (int i = Ls[rp]; i; i = Nxt[i]) {
         flag = 1;
         for (int j = 1; j <= n; j++) 
              if (x[j] != Hash[i][j]) {
                  flag = 0; break;
              }
         if (flag) return 0;
    }
    ++cnt;
    for (int i = 1; i <= n; i++) Hash[cnt][i] = x[i];
    Nxt[cnt] = Ls[rp], Ls[rp] = cnt; 
    return 1;
}

void bfs() {
    queue <int> Q[N];
    queue <int> F;
    for (int i = 1; i <= n; i++) Q[i].push(a[i]);
    F.push(0);
    Check(a);
    int cp[N], rp[N];
    bool flag;
    while (!F.empty()) {
           for (int i = 1; i <= n; i++) 
                cp[i] = Q[i].front(), Q[i].pop();
           int tp = F.front();
           F.pop();
           for (int i = 1; i <= n; i++) rp[i] = cp[d1[i]];
           if (Check(rp)) {
               flag = 1;
               for (int j = 1; j <= n; j++) 
                    if (rp[j] != b[j]) {
                       flag = 0; break;
                    }
               if (flag) {
                   printf("%d\n", tp + 1);
                   exit(0);
               }
               for (int i = 1; i <= n; i++) Q[i].push(rp[i]);
               F.push(tp + 1);
           }

           for (int i = 1; i <= n; i++) rp[i] = cp[d2[i]];
           if (Check(rp)) {
               flag = 1;
               for (int j = 1; j <= n; j++) 
                    if (rp[j] != b[j]) {
                        flag = 0;
                        break;
                    }
               if (flag) {
                   printf("%d\n", tp + 1);
                   exit(0);
               }
               for (int i = 1; i <= n; i++) Q[i].push(rp[i]);
               F.push(tp + 1);
           }
    }
}

int main() {
    scanf("%d", &n);
    Init(n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    memcpy(b, a, sizeof(a));
    sort(b + 1, b + n + 1);
    bool flag = 1;
    for (int j = 1; j <= n; j++) 
         if (a[j] != b[j]) {
             flag = 0; break;
         }
    if (flag) {
        printf("0\n");
        return 0;
    }
    bfs();
    printf("No Answer\n");
    return 0;
}

你可能感兴趣的:(C++,广搜bfs,哈希)