Kuangbin专题二搜索进阶

kuangbin专题二搜索进阶

A - Eight HDU - 1043

用康托展开来状态压缩,方便记录路径。另外路径反着记。最后他娘的竟然打表,无耻。
八种方法


#include <string>
#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <cmath>
using namespace std;
typedef pair<int, int> P;
#define N 9
#define M 400000
const int INF = 0x3f3f3f3f;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

struct node{
  char ope;
  int fa;
  node(char c = 'l', int FA = -1):ope(c),fa(FA){}
};
struct Node{
  string s;
  int can, n;
  Node(string S="", int Can=0, int NN=0):s(S), can(Can), n(NN){}
};
char ch[N];
queue<Node> que;
int fac[N];
node path[M];
string goal;
char ope[] = "lrud";
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};

int cantor(string num){
    int ans = 0;
    rep(i, 0, N - 1) {
        int sm = 0;
        rep(j, i + 1, N - 1) if(num[i] > num[j]) sm++;
        ans += sm * fac[N - i - 1];
    }
    return ans;
}

void bfs()
{
    que.push(Node(goal, 0, 8));
    path[0].fa = 0;
    Node h;
    int x, y, xx, yy, index, tmp;
    string s;
    while(!que.empty()){
        h = que.front(); que.pop();
        rep(i, 0, 3){
            x = h.n / 3; y = h.n % 3;
            xx = x + dx[i]; yy = y + dy[i];
            index = xx * 3 + yy;
            if(xx < 0 || xx > 2 || yy < 0 || yy > 2) continue;
            if(index > 8 || index < 0) continue;

            s = h.s;
            swap(s[h.n], s[index]);

            tmp = cantor(s);
            if(path[tmp].fa != -1) continue;

            path[tmp] = node(ope[i], h.can);
            que.push(Node(s, tmp, index));
        }
    }
}

int main()
{
    //freopen("data.txt", "r", stdin);

    fac[0] = 1;
    rep(i, 1, N) fac[i] = fac[i - 1] * i;
    goal.clear(); rep(i, 1, N) goal += char('0' + i);
    bfs();

    string num = "";
    while(cin >> ch[0]){
        num.clear();
        rep(i, 1, N - 1) cin >> ch[i];
        rep(i, 0, N - 1) if(ch[i] == 'x') num += '9';
        else num += ch[i];

        int s = cantor(num);

        if(path[s].fa == -1) puts("unsolvable");
        else {
            while(s){
                putchar(path[s].ope);
                s = path[s].fa;
            }
            putchar('\n');
        }
    }

    return 0;
}

B - Eight II HDU - 3567

宝宝心里苦啊,这个代码调处来不容易啊。
我是用的网上的那个建立映射来写的。具体细节和上一题差不多,就是建立了了映射,不得不说这个映射建立的真是骚气。这题大大小小的错误卡了我这么久,稍微写一下注释。

#include <string>
#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <cmath>
using namespace std;
typedef pair<int, int> P;
#define N 9
#define M 500000
const int INF = 0x3f3f3f3f;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

struct node{
  char ope;///operation 记录操作
  int fa;///老爸。
  node(){fa = -1;}///初始化为-1于是祖先的fa值为-1
};
struct Node{
  char s[10];///tmd用string会超时
  int can, n, ind;///can是康托哈希出来的值,n是9所在的下标,ind是祖宗的类型
  Node(){}
  Node(const char * S, int Can, int NN, int Ind):can(Can), n(NN), ind(Ind){
      rep(i, 0, 9) s[i] = S[i];
  }
  void set(const char * S, int Can, int NN, int Ind){
      rep(i, 0, 9) s[i] = S[i];;can = Can;n = NN; ind = Ind;
  }
};

queue<Node> que;
int fac[N];
node path[N][M];
char ope[] = "dlru";///这个玩意儿的方向要注意字典序
int dx[4] = {1, 0, 0, -1};
int dy[4] = {0, -1, 1, 0};
///一开始为了优化时间把各种操作写出来了
char op[10][4] = {{0,2}, {0,1,2}, {0,1}, {0,2,3}, {0,1,2,3}, {0,1,3}, {2,3}, {1,2,3}, {1,3}};
int cnt[10] = {2,3,2,3,4,3,2,3,2};
char a[10], b[10];
int pa, pb, ca, cb;
int t, l;
char ans[M];
bool vis[N][M];
int ed[N];

int cantor(const char * num){
    int ans = 0;
    rep(i, 0, N - 1) {
        int sm = 0;
        rep(j, i + 1, N - 1) if(num[i] > num[j]) sm++;
        ans += sm * fac[N - i - 1];
    }
    return ans;
}

void bfs()
{
    Node tmp;
    tmp.set("123456789", ed[8] = cantor("123456789"), 8, 8); que.push(tmp); vis[8][ed[8]] = true;
    tmp.set("123456798", ed[7] = cantor("123456798"), 7, 7); que.push(tmp); vis[7][ed[7]] = true;
    tmp.set("123456978", ed[6] = cantor("123456978"), 6, 6); que.push(tmp); vis[6][ed[6]] = true;
    tmp.set("123459678", ed[5] = cantor("123459678"), 5, 5); que.push(tmp); vis[5][ed[5]] = true;
    tmp.set("123495678", ed[4] = cantor("123495678"), 4, 4); que.push(tmp); vis[4][ed[4]] = true;
    tmp.set("123945678", ed[3] = cantor("123945678"), 3, 3); que.push(tmp); vis[3][ed[3]] = true;
    tmp.set("129345678", ed[2] = cantor("129345678"), 2, 2); que.push(tmp); vis[2][ed[2]] = true;
    tmp.set("192345678", ed[1] = cantor("192345678"), 1, 1); que.push(tmp); vis[1][ed[1]] = true;
    tmp.set("912345678", ed[0] = cantor("912345678"), 0, 0); que.push(tmp); vis[0][ed[0]] = true;

    Node h;
    int xx, yy, index, tp;
    char s[10];
    while(!que.empty()){
        h = que.front(); que.pop();
        rep(i, 0, cnt[h.n] - 1) {
            xx = h.n / 3 + dx[op[h.n][i]]; yy = h.n % 3 + dy[op[h.n][i]];
            index = xx * 3 + yy;

            strcpy(s, h.s);
            swap(s[h.n], s[index]);

            tp = cantor(s);
            if(vis[h.ind][tp]) continue;

            vis[h.ind][tp] = true;
            path[h.ind][tp].ope = ope[op[h.n][i]];
            path[h.ind][tp].fa = h.can;
            que.push(Node(s, tp, index, h.ind));
        }
    }
}

int main()
{
    //freopen("data.txt", "r", stdin);

    fac[0] = 1;
    rep(i, 1, N) fac[i] = fac[i - 1] * i;
    bfs();

    scanf("%d", &t);
    rep(Case, 1, t){
        scanf("%s%s", a, b);
    ///这里多写了个elsemmp
        rep(i, 0, N - 1) if(a[i] == 'X') a[i] = '9', pa = i;
        rep(i, 0, N - 1) if(b[i] == 'X') b[i] = '9', pb = i;

        int cast[10], id = 1;
        rep(i, 0, N - 1) if(a[i] != '9')cast[a[i] - '0'] = id++;
        else cast[9] = 9;

        rep(i, 0, N - 1) b[i] = cast[b[i] -'0'] + '0';

        cb = cantor(b);
        l = 0;
        while(cb != ed[pa]){
            ans[l++] = path[pa][cb].ope;
            cb = path[pa][cb].fa;///这里写成了ca
        }
        printf("Case %d: %d\n", Case, l);
        for(int i = l - 1; i >= 0; i--) putchar(ans[i]);
        putchar('\n');
    }

    return 0;
}

C - 哈密顿绕行世界问题 HDU - 2181

突然来了一道简单题。

#include <string>
#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;
typedef pair<int, int> P;
#define N 21
#define M 500000
const int INF = 0x3f3f3f3f;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int g[N][3], ans[N];
bool vis[N];
int m, l;
int a, b, c;

void dfs(int fa, int deep)
{
    if(deep == N - 1){
        printf("%d:  ", ++l);
        rep(i, 0, 19) printf("%d ", ans[i]);
        printf("%d\n", m);
        return;
    }

    if(vis[a] && vis[b] && vis[c]) return;

    rep(i, 0, 2) {
        if(!vis[g[fa][i]]){
            vis[g[fa][i]] = true;
            ans[deep] = g[fa][i];
            dfs(g[fa][i], deep + 1);
            vis[g[fa][i]] = false;
        }
    }
}

int main()
{
    //freopen("data.txt", "r", stdin);

    rep(i, 1, 20) rep(j, 0, 2) scanf("%d", &g[i][j]);
    rep(i, 1, 20) sort(g[i], g[i] + 3);

    while(~scanf("%d", &m) && m){
        a = g[m][0]; b = g[m][1]; c = g[m][2];
        memset(vis, false, sizeof vis);
        l = 0;
        ans[0] = m;
        vis[m] = true;
        dfs(m, 1);
    }

    return 0;
}

D - Escape HDU - 3533

这题本来是普通的宽搜,只是加上了一个时间维度。
因为机智的直接百度,所以我看到了子弹不能穿过城堡这个点。
mmp宽搜里忘了写vis导致ME了好久。
我是先把子弹预处理出来了,直接标记vis,百度的时候也有走到哪儿就判断一下的,数据比较弱可能吧。

#include <string>
#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;
//typedef pair<int, int> P;
#define N 101
#define M 1001
const int INF = 0x3f3f3f3f;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

bool vis[N][N][M];
int g[N][N];
int dx[] = {0, 0, 0, 1, -1};
int dy[] = {0, 1, -1, 0, 0};
int n, m, k, d, t, v, x, y;
char c;
struct node{
  int c, t, v, x, y;
}ope[N];
struct P{
  int first, second, d;
  P(int x=0, int y=0, int d=0):first(x),second(y), d(d){}
};
queue<P> que;

bool ok(int x, int y){
    return 0 <= x && x <= n && 0 <= y && y <= m;
}
int geted(node & t)
{
    int c = t.c, x = t.x, y = t.y;
    int cnt = 0;
//cout << c << ' ' << ' ' << t.v << ' ' << x << ' ' << y << endl;
    while(ok(x + dx[c], y + dy[c])){
        x += dx[c]; y += dy[c];  //cout << "xy " << x << ' ' << y << ' ' endl;
        if(g[x][y]) break;
        if(c == 1 && (y - t.y) % t.v == 0) cnt++;
        else if(c == 2 && (t.y - y) % t.v == 0) cnt++;
        else if(c == 3 && (x - t.x) % t.v == 0) cnt++;
        else if(c == 4 && (t.x - x) % t.v == 0) cnt++;
     }
     return cnt;
}

int bfs()
{
    while(!que.empty()) que.pop();
    que.push(P(0, 0, d));

    while(!que.empty()){
        P h = que.front(); que.pop();
        if(h.fi == n && h.se == m) return d - h.d;
        if(h.d <= 0 || h.d < (m + n - h.fi - h.se - 1)) continue;
    //   cout << h.d;
        rep(i, 0, 4){
            x = h.fi + dx[i]; y = h.se + dy[i];
            if(!ok(x, y) || vis[x][y][d - h.d + 1] || g[x][y]) continue;
//if(h.d == 9) cout <<"i "<<i<<endl;
            vis[x][y][d - h.d + 1] = true;
            que.push(P(x, y, h.d - 1));
        }
    }
    return -1;
}

int main()
{
    //freopen("data.txt", "r", stdin);
    while(~scanf("%d%d%d%d", &n, &m, &k, &d)){
        memset(vis, false, sizeof vis);
        memset(g, 0, sizeof g);
        rep(i, 0, k - 1) {
            cin >> c;
            if(c == 'E') ope[i].c = 1;
            else if(c == 'W') ope[i].c = 2;
            else if(c == 'S') ope[i].c = 3;
            else if(c == 'N') ope[i].c = 4;
            cin >> ope[i].t >> ope[i].v >> ope[i].x >> ope[i].y;
            g[ope[i].x][ope[i].y] = 1;
        }

        int x, y;
        rep(i, 0, k - 1) {
            c = ope[i].c;
            int ed = geted(ope[i]);//cout << "ed"<<ed << endl;
            x = ope[i].x; y = ope[i].y;
            rep(j, 1, ed){
                x += dx[c] * ope[i].v; y += dy[c] * ope[i].v;
              //  cout << x << ' ' << y << ' ' << j << endl;
                for(int z = 0; j + z * ope[i].t <= d; z++)
                    vis[x][y][j + z * ope[i].t] = true;
            }
        }
//cout << vis[2][0][4] << ' ' << vis[2][1][7]<< endl;
        int ans = bfs();
        if(ans == -1) puts("Bad luck!");
        else printf("%d\n", ans);
    }

    return 0;
}

E - DNA sequence HDU - 1560

我就写过刘汝佳上的一道迭代加深搜索,所以直接学的网上的代码(不百度根本不知道只是IDA*,还觉得是模拟)。
学习于这里

#include <string>
#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;
typedef pair<int, int> P;
#define N 10
#define M 1001
const int INF = 0x3f3f3f3f;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

char s[10][5], c[] = "ACGT";
int n, m, sum, res, t;
bool ans;
int len[10], pos[10];

int getlen()
{
    int mx = 0;
    rep(i, 0, n - 1) mx = max(mx, len[i] - pos[i]);
    return mx;
}

int dfs(int deep)
{
    int t = getlen();
    if(t + deep > res) return t + deep - res;
    if(!t){
        ans = true; return 0;
    }

    int mx = 0, tmp[10];
    memcpy(tmp, pos, sizeof pos);
    rep(i, 0, 3){
        bool flag = false;
        rep(j, 0, n - 1) if(s[j][pos[j]] == c[i])
            flag = true, pos[j]++;
        if(flag){
            int t = dfs(deep + 1);
            if(ans) return 0;
            mx = max(t, mx);
            memcpy(pos, tmp, sizeof tmp);
        }
    }
    return mx;
}

void ida()
{
    int t = 0;
    ans = false;
    while(true){
        t = dfs(0);
        if(ans) return;
        res += t;
    }
}

int main()
{
    ///freopen("data.txt", "r", stdin);

    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        res = 0;

        rep(i, 0, n - 1){
            scanf("%s", s[i]);
            len[i] = strlen(s[i]);
            res = max(res, len[i]);
            pos[i] = 0;
        }

        ida();
        printf("%d\n", res);
    }

    return 0;
}

F - Magic Cube ZOJ - 2477

tmd这辈子都不写模拟题了要老命。
吐槽vj的显示,爬数据就不能好好显示吗。
真正的字母

vj的字母

预处理出所有可能的操作,六个面,每个面只有2种,一共12
种。不超过5层,就算12^5的复杂度,直接IDA*一层一层来。

学的这个博客的:点击打开链接

#include <string>
#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;
typedef pair<int, int> P;
#define N 55
#define M 1001
const int INF = 0x3f3f3f3f;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
///*
//         1  2  3
//         4  5  6
//         7  8  9
//10 11 12 13 14 15 16 17 18 19 20 21
//22 23 24 25 26 27 28 29 30 31 32 33
//34 35 36 37 38 39 40 41 42 43 44 45
//         46 47 48
//         49 50 51
//         52 53 54
//*/
int cent[7] = {23, 26, 29, 32, 5, 50};
int face[7][10] = {
{10,11,12,22,23,24,34,35,36},
{13,14,15,25,26,27,37,38,39},
{16,17,18,28,29,30,40,41,42},
{19,20,21,31,32,33,43,44,45},
{1,2,3,4,5,6,7,8,9},
{46,47,48,49,50,51,52,53,54}
};
int change[12][20] = {       
                   {1,4,7,13,25,37,46,49,52,21,33,45,10,11,12,24,36,35,34,22},
                   {45,33,21,1,4,7,13,25,37,52,49,46,34,22,10,11,12,24,36,35},
                   {7,8,9,16,28,40,48,47,46,36,24,12,13,14,15,27,39,38,37,25},
                   {36,24,12,7,8,9,16,28,40,48,47,46,37,25,13,14,15,27,39,38},
                   {9,6,3,19,31,43,54,51,48,39,27,15,16,17,18,30,42,41,40,28},
                   {39,27,15,9,6,3,19,31,43,54,51,48,40,28,16,17,18,30,42,41},
                   {42,30,18,3,2,1,10,22,34,52,53,54,19,20,21,33,45,44,43,31},
                   {52,53,54,42,30,18,3,2,1,10,22,34,43,31,19,20,21,33,45,44},
                   {15,14,13,12,11,10,21,20,19,18,17,16,1,2,3,6,9,8,7,4},
                   {18,17,16,15,14,13,12,11,10,21,20,19,7,4,1,2,3,6,9,8},
                   {37,38,39,40,41,42,43,44,45,34,35,36,46,47,48,51,54,53,52,49},
                   {34,35,36,37,38,39,40,41,42,43,44,45,52,49,46,47,48,51,54,53}
                  } ;


char s[N];
int t, res;
int a[10], b[10];

char getch(){
    char c; while((c = getchar()) == ' ' || c == '\n');
    return c;
}

int geth(char * s)
{
    int mx = 0;
    rep(i, 0, 5) rep(j, 0, 8)
        if(s[face[i][j]] != s[cent[i]]) mx++;
    return (mx + 11) / 12;
}

bool dfs(int deep)
{
    int t = geth(s);
    if(t + deep > res) return false;
    if(!t) return true;

    char tmp[N];
    memcpy(tmp, s, sizeof s);
    rep(i, 0, 11){
        rep(j, 0, 19) s[change[i][j]] = tmp[change[i^1][j]];

        a[deep] = i / 2;
        b[deep] = i & 1?-1:1;

        if(dfs(deep + 1)) return true;
        memcpy(s, tmp, sizeof tmp);
    }
    return false;
}

void ida()
{
    res = geth(s);

    if(!res) {printf("0\n"); return;}
    res = 1;
    while(res <= 5){
        if(dfs(0)){
            printf("%d\n", res);
            rep(i, 0, res - 1) printf("%d %d\n", a[i], b[i]);
            return;
        }
        res++;
    }
    printf("-1\n");
}

int main()
{
   // freopen("data.txt", "r", stdin);

    scanf("%d", &t);
    while(t--){
        rep(i, 1, N - 1) s[i] = getch();
        ida();
    }

    return 0;
}

H - Gap HDU - 1067

哈希哈希,太难了哈希,上次我哈希宽搜是什么时候了。。。还是做的太少了。(其实map就挺好)。
转载链接

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<utility>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<iterator>
#include<stack>
using namespace std;
const int INF=1e9+7;
const double eps=1e-8;
typedef __int64 LL;
const LL mod=1000007;
typedef pair<int, int> P;
#define N 801
#define M 1001
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int maze[4][8];
LL Hash[mod];
LL base[32];
struct node{
    int px[4],py[4];
    int S[4][8];
    int dist;
}Nod[100005];
int id;
queue<int> que;

int goal[4][8]={
{ 11,12,13,14,15,16,17,0 },
{ 21,22,23,24,25,26,27,0 },
{ 31,32,33,34,35,36,37,0 },
{ 41,42,43,44,45,46,47,0 }
};
LL G;

int GetId(int x,int y){ return x*8+y; }

LL GetHash(int S[4][8])
{
    LL ret=0;
    for(int i=0;i<4;i++)
        for(int j=0;j<8;j++) ret+=(LL)S[i][j]*base[GetId(i,j)];
    return ret;
}
bool InsertHash(LL val){
   LL v=val%mod;
   while(Hash[v]!=-1&&Hash[v]!=val)  v=(v+10)%mod;
   if(Hash[v]==-1){ Hash[v]=val; return true; }
   return false;
}

void Change_S(node& e,int x,int y,int pick,int k)
{
    rep(i, 0, 3) rep(j, 0, 7) if(e.S[i][j]==pick){
        e.S[i][j]=0; e.S[x][y]=pick; e.px[k]=i; e.py[k]=j;
        return;
    }
}
void AddNode(int now)
{
    node& e = Nod[now];
    rep(i, 0, 3){
        int x=e.px[i], y=e.py[i];
        int pre = e.S[x][y - 1];
        if(pre == 0 || e.S[x][y - 1] % 10 == 7) continue;

        node t = e;
        t.dist++;
        Change_S(t, x, y, e.S[x][y - 1] + 1, i);
        LL nowG=GetHash(t.S);
        if(!InsertHash(nowG)) continue;

        int cur=id++;
        Nod[cur]=t;
        que.push(cur);
    }
}
int bfs()
{
    rep(i, 0, 3) rep(j, 1, 7){
        int a=maze[i][j]/10;
        int b=maze[i][j]%10;
        if(b==1) { maze[a-1][0]=maze[i][j]; maze[i][j]=0; }
    }
    memset(Hash,-1,sizeof(Hash));
    while(!que.empty())  que.pop();
    id=0;
    G=GetHash(goal);
    int k=0;
    int cur=id++;
    rep(i, 0, 3) rep(j, 0, 7){
        Nod[cur].S[i][j] = maze[i][j];
        if(maze[i][j] == 0){ Nod[cur].px[k]=i; Nod[cur].py[k++]=j; }
    }
    Nod[cur].dist=0;
    que.push(cur);
    while(!que.empty()){
        int now=que.front(); que.pop();
        node & e=Nod[now];
        LL nowG=GetHash(e.S);
        if(nowG==G) return e.dist;
        AddNode(now);
    }
    return -1;
}
int main()
{
    //freopen("data.txt", "r", stdin);
    int t;
    base[0] = 1; rep(i, 1, 31) base[i] = base[i - 1] * 2;
    scanf("%d", &t);
    while(t--)
    {
        memset(maze,0,sizeof(maze));
        rep(i, 0, 3) rep(j, 1, 7) scanf("%d", &maze[i][j]);
        printf("%d\n", bfs());
    }
    return 0;
}

I - A计划 HDU - 2102

虽然是普通的多维bfs,但是还是wa了两发。

#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;
typedef pair<int, int> P;
#define N 11
#define M 100001
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
#define fi first
#define se second 考虑好,
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

struct node{
    int d, x, y;
    bool operator < (const node & t) const{
        if(d == t.d) {
            if(x == t.x){
                return y < t.y;
            }
            return x < t.x;
        }
        return d < t.d;
    }
    node(int d, int x, int y):d(d), x(x), y(y){}
};
queue<node> que;
char maze[2][N][N];
int d[2][N][N];
int n, m, time;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};

bool bfs()
{
    while(!que.empty()) que.pop();
    memset(d, 0, sizeof d);
    que.push(node(0, 0, 0));
    d[0][0][0] = 0;

    while(!que.empty()){
        node h = que.front(); que.pop();
        if(maze[h.d][h.x][h.y] == 'P') return true;
        if(d[h.d][h.x][h.y] == time) continue;

        maze[h.d][h.x][h.y] = '*';
        rep(i, 0, 3) {
            int x = h.x + dx[i], y = h.y + dy[i];
            if(x < 0 || x >= n || y < 0 || y >= m) continue;
            if(maze[h.d][x][y] == '*') continue;
            if(maze[h.d][x][y] == '#') {
                maze[h.d][x][y] = '*';
                if(maze[h.d^1][x][y] == '*' || maze[h.d^1][x][y] == '#') continue;
                que.push(node(h.d^1, x, y));
                d[h.d^1][x][y] = d[h.d][h.x][h.y] + 1;
                continue;
            }
            que.push(node(h.d, x, y));
            d[h.d][x][y] = d[h.d][h.x][h.y] + 1;
        }
    }
    return false;
}

int main()
{
   // freopen("data.txt", "r", stdin);

    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d%d%d", &n, &m, &time);
        rep(k, 0, 1)rep(i, 0, n - 1) rep(j, 0, m - 1) cin >> maze[k][i][j];
        printf(bfs()?"YES\n":"NO\n");
    }

    return 0;
}

J - Travelling HDU - 3001

第一次做状压dp的题,看博客蛮好懂的。dp[i][j]表示以i为终点在状态j下的最短路值。(不是搜索专题吗???状压宽搜也行?)
参考链接

#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;
typedef pair<int, int> P;
#define N 11
#define M 100001
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
#define fi first
#define se second 考虑好,
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)

int n, m, ans, three[N], cnt, g[N][N], dp[N][60005];
int a, b, c;
int w[N];

int getn(int d)
{
    int num = 0;
    rep(i, 0, n - 1) {
        w[i] = d % 3;
        d /= 3;
        if(w[i]) num++;
    }
    return num;
}

int main()
{
    freopen("data.txt", "r", stdin);
    three[0] = 1;
    rep(i, 1, 10) three[i] = three[i - 1] * 3;

    while(~scanf("%d%d", &n, &m)){
        memset(g, -1, sizeof g);
        memset(dp, -1, sizeof dp);
        while(m--){
            scanf("%d%d%d", &a, &b, &c);
            a--; b--;
            if(g[a][b] == -1) g[a][b] = g[b][a] = c;
            else g[a][b] = g[b][a] = min(g[a][b], c);
        }
        ans = INF;
        rep(j, 1, three[n] - 1) {
            cnt = getn(j);//cout << "cnt " << cnt << endl;
            rep(i, 0, n - 1) if(w[i]) {
                if(cnt == 1) dp[i][j] = 0;
                if(dp[i][j] == -1) continue;
                if(cnt == n) ans = min(dp[i][j], ans);
                rep(k, 0, n - 1) if(k != i && w[k] < 2 && g[i][k] != -1){
                    int tj = j + three[k];
                    if(dp[k][tj] == -1) dp[k][tj] = dp[i][j] + g[i][k];
                    else dp[k][tj] = min(dp[k][tj], dp[i][j] + g[i][k]);
                }
            }
        }

        if(ans == INF) puts("-1");
        else printf("%d\n", ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40379678/article/details/80980701