kuangbin专题二:搜索进阶

前:这节以后,我尽可能的增加代码的可读性,为此将牺牲一定程度的简洁。

 

HDU1043 Eight

思路:cantor展开。

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 372880;
int factor[10];
int ary[10];
bool vis[maxn];
string Path[maxn];
char op[] = {'u', 'd', 'l', 'r'};
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};

int cantor(int *ary, int n){
    int res = 0;
    for(int i = 0; i < n; i++){
        int small = 0;
        for(int j = i + 1; j < n; j++)
            if(ary[j] < ary[i]) small++;
        res += small * factor[n - 1 - i];
    }
    return res;
}

void decantor(int *ary, int n, int k){
    vector<int> vec;
    for(int i = 0; i < 9; i++) vec.push_back(i);
    for(int i = 0; i < 9; i++){
        int t = k / factor[n - 1 - i];
        k %= factor[n - 1 - i];
        ary[i] = vec[t];
        vec.erase(vec.begin() + t);
    }
}

void bfs(){
    for(int i = 0; i < 9; i++) ary[i] = (i + 1) % 9;
    queue<int> q;
    int st = cantor(ary, 9);
    q.push(st);
    vis[st] = true;
    Path[st] = "";
    while(q.size()){
        int p = q.front(); q.pop();
        decantor(ary, 9, p);
        int zero = find(ary, ary + 9, 0) - ary;
        int x = zero / 3, y = zero % 3;
        for(int i = 0; i < 4; i++){
            int nx = x + dx[i], ny = y + dy[i];
            if(nx>=0 && nx<3 && ny>=0 && ny<3){
                int newzero = nx * 3 + ny;
                swap(ary[zero], ary[newzero]);
                int nxt = cantor(ary, 9);
                if(!vis[nxt]){
                    vis[nxt] = true;
                    Path[nxt] = op[i] + Path[p];
                    q.push(nxt);
                }
                swap(ary[zero], ary[newzero]);
            }
        }
    }
}

void init(){
    factor[0] = 1;
    for(int i = 1; i <= 9; i++) factor[i] = factor[i-1] * i;
}


int main(){
    init();
    bfs();
    char c;
    while(cin >> c){
        ary[0] = c == 'x' ? 0 : c - '0';
        for(int i = 1; i < 9; i++){
            cin >> c;
            ary[i] = c == 'x' ? 0 : c - '0';
        }
        int value = cantor(ary, 9);
        if(!vis[value]) cout << "unsolvable" << endl;
        else cout << Path[value] << endl;
    }
    return 0;
}
View Code

 

HDU3567 Eight II

思路: 双向bfs,但是一直WA。。。先挖坑以后再填。

 

HDU2181 哈密顿绕行世界问题

思路:简单回溯法,注意输出格式。

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 372880;
int edge[22][3];
bool vis[22];
int Path[22];

int resn;
void Print(){
    cout << ++resn << ":  ";
    for(int i = 1; i <= 20; i++)
        cout << Path[i] << ' ';
    cout << Path[21] << endl;
}

void dfs(int dep, int city, int st){
    if(dep == 20) {
        for(int i = 0; i < 3; i++){
            int v = edge[city][i];
            if(v == st){
                Path[dep] = city;
                Path[dep+1] = st;
                Print();
            }
        }
        return;
    }
    vis[city] = true;
    Path[dep] = city;
    for(int i = 0; i < 3; i++){
        int v = edge[city][i];
        if(!vis[v]){
            dfs(dep+1, v, st);
        }
    }
    vis[city] = false;
}

int main(){
    for(int i = 1; i <= 20; i++)
        for(int j = 0; j < 3; j++)
            cin >> edge[i][j];
    int m;
    while(cin >> m && m){
        resn = 0;
        dfs(1, m, m);
    }
    return 0;
}
View Code

 

HDU3533 Escape

思路:巨坑的题目,坑如下:

  1. 碉堡不能经过,这点题目里没说。
  2. 人可以穿过子弹,只要人和子弹不在同一时间同一地点。
  3. 敌军碉堡可以建立在我方基地(???)。
#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 105;
int n, m, k, d;
int mm[maxn][maxn];
bool vis[maxn][maxn][1005];
int dx[] = {1, -1, 0, 0, 0}, dy[] = {0, 0, 1, -1, 0};
char invdir[] = {'N', 'S', 'W', 'E'};

struct Castle{
    char dir;
    int t, v;
} castle[maxn];

void init(){
    memset(mm, 0, sizeof(mm));
    memset(vis, false, sizeof(vis));
}

void read_castle(int casNum){
    for(int i = 1; i <= casNum; i++){
        int x, y;
        cin >> castle[i].dir >> castle[i].t >> castle[i].v;
        cin >> x >> y;
        mm[x][y] = i;
    }
}

inline bool in_map(int x, int y){
    return x>=0 && x<=m && y>=0 && y<=n;
}

bool can_hit(Castle &ca, int nx, int ny, int x, int y, int tt, int dirN){
    if(ca.dir != invdir[dirN]) return false;
    int diff = abs(nx - x) + abs(ny - y);
    if((diff % ca.v == 0) && (diff <= tt * ca.v) && ((tt - diff / ca.v) % ca.t == 0))
        return true;
    return false;
}

bool is_safe(int x, int y, int tt){
    if(!in_map(x, y) || mm[x][y]) return false;
    for(int i = 0; i < 4; i++){
        int nx = x, ny = y;
        while(in_map(nx, ny) && !mm[nx][ny]) nx += dx[i], ny += dy[i];
        if(in_map(nx, ny)){
            Castle &ca = castle[mm[nx][ny]];
            if(can_hit(ca, nx, ny, x, y, tt, i))
                return false;
        }
    }
    return true;
}

struct Pos{
    int x, y, t;
};

int bfs(){
    queue<Pos> q;
    Pos st{0, 0, 0};
    q.push(st);
    vis[0][0][0] = true;
    while(q.size()){
        Pos p = q.front(); q.pop();
        if(p.t > d) return 0;
        if(p.x == m && p.y == n) return p.t;
        for(int i = 0; i < 5; i++){
            int nx = p.x + dx[i], ny = p.y + dy[i];
            int nt = p.t + 1;
            if(!vis[nx][ny][nt] && is_safe(nx, ny, nt)){
                Pos tmp{nx, ny, nt};
                q.push(tmp);
                vis[nx][ny][nt] = true;
            }
        }
    }
    return 0;
}

int main(){
    while(cin >> m >> n >> k >> d){
        init();
        read_castle(k);
        int res = bfs();
        if(res == 0) cout << "Bad luck!" << endl;
        else cout << res << endl;
    }
}
View Code

 

HDU1560 DNA sequence

 思路:题目数据比较水,用A*可过(疯狂TLE)。看到题目第一反应是DP,但没想到比较简单的做法。

#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 10;
int n;
int pos[maxn], left_len;
string element = "ACGT";
string DNA[maxn];

int estimate(){
    int res = 0;
    for(int i = 0; i < n; i++)
        res = max(res, (int)(DNA[i].length() - pos[i]));
    return res;
}

bool found;
int max_dep;
void dfs(int dep){
    if(dep + estimate() > max_dep) return;
    else if(left_len == 0){
        found = true;
        return;
    }

    int tmp[maxn], orign_len = left_len;
    for(int i = 0; i < n; i++)
        tmp[i] = pos[i];

    for(int i = 0; i < 4; i++){
        bool match = false;
        for(int j = 0; j < n; j++){
            if(pos[j] < DNA[j].length() && DNA[j][pos[j]] == element[i]){
                match = true;
                pos[j]++;
                left_len--;
            }
        }

        if(match){
            dfs(dep+1);
            if(found) return;
            // cancel above changes
            for(int j = 0; j < n; j++){
                pos[j] = tmp[j];
            }
            left_len = orign_len;
        }
    }
}

void read_data(){
    cin >> n;
    left_len = 0;
    max_dep = 0;
    found = false;
    memset(pos, 0, sizeof(pos));
    for(int i = 0; i < n; i++){
        cin >> DNA[i];
        left_len += DNA[i].length();
        max_dep = max(max_dep,(int)DNA[i].length());
    }
}

int main(){
    int t;
    cin >> t;
    while(t--){
        read_data();
        while(true){
            dfs(0);
            if(found) break;
            max_dep++;
        }
        cout << max_dep << endl;
    }
}
View Code

 

ZOJ2477 Magic Cube

 思路:题目很简单,但是代码有点琐碎,节约时间,先挖个坑。

 

HDU3085 Nightmare Ⅱ

 

posted @ 2020-11-01 09:31  Nanachi  阅读(92)  评论(0)    收藏  举报