DFS and Similar系列

EOJ 1646/POJ 3126 Prime Path


把一個四位質數變爲另一個四位質數,要求每次只能改動一位數,且變化過程中產生的數也是四位質數。

先篩出質數,然後普通bfs。

#include<bits/stdc++.h>
using namespace std;

int prime[10000];
string s, t;
bool vis[10000];

void init()
{
    for (int i = 2; i < 10000; ++i)
        prime[i] = 1;
    for (int i = 2; i < 10000; ++i)
        if (prime[i])
            for (int j = i*i; j < 10000; j += i)
                prime[j] = 0;
}

int toint(string str)
{
    int num = 0;
    for (int i = 0; i < 4; ++i)
        num = num * 10 + str[i] - '0';
    return num;
}

int bfs()
{
    memset(vis, 0, sizeof(vis));
    queue<pair<string, int> > q;
    q.push(make_pair(s, 0));
    while (!q.empty()) {
        string a = q.front().first;
        int cnt = q.front().second;
        q.pop();
        if (a == t) return cnt;
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j <= 9; ++j) {
                if (!i && !j) continue;
                string b = a;
                b[i] = j + '0';
                int num = toint(b);
                if (!vis[num] && prime[num]) {
                    vis[num] = 1;
                    q.push(make_pair(b, cnt+1));
                }
            }
        }
    }
    return -1;
}

int main()
{
    init();
    int cas;
    cin >> cas;
    while (cas--) {
        cin >> s >> t;
        int ans = bfs();
        if (ans == -1) printf("Impossible\n");
        else printf("%d\n", ans);
    }
    return 0;
}

EOJ 3369 三千米健身步道


n座教學樓,n-1條長爲1km的道路,求建設3km的健身步道有多少種方案。起點和終點交換算同一種。

鄰接矩陣無向圖dfs,控制遞歸層數爲3。由於起點終點交換隻算一種,所以最後答案除以2。

#include <bits/stdc++.h>
using namespace std;

const int N = 1005;
vector<int> g[N];

int n;
bool vis[N];

int dfs(int i, int dep)
{
    if(dep == 3) return 1;
    int sum = 0;
    vis[i] = 1;
    for(int j = 0; j < g[i].size(); ++j)
        if (!vis[g[i][j]]) sum += dfs(g[i][j], dep+1);
    vis[i] = 0;
    return sum;
}

int main()
{
    int u, v;
    cin >> n;
    for(int i = 1; i < n; ++i) {
        scanf("%d%d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    memset(vis, 0, sizeof vis);
    int cnt = 0;
    for(int i = 1; i <= n; ++i)
        cnt += dfs(i, 0);
    cout << cnt / 2 << endl;
    return 0;
}

EOJ 3260(ECNU大學生程序設計邀請賽C.)袋鼠媽媽找孩子


袋鼠媽媽找不到她的孩子了。她的孩子被怪獸抓走了。
袋鼠媽媽現在在地圖的左上角,她的孩子在地圖第 x 行第 y 列的位置。怪獸想和袋鼠媽媽玩一個遊戲:他不想讓袋鼠媽媽過快地找到她的孩子。袋鼠媽媽每秒鐘可以向上下左右四個方向跳一格(如果沒有牆阻攔的話),怪獸就要在一些格子中造牆,從而完成一個迷宮,使得袋鼠媽媽能夠找到她的孩子,但最快不能小於 k 秒。
請設計這樣一個迷宮。

把地圖初始化爲牆,然後從終點開始dfs嘗試破壞掉牆來開闢道路直到起點。之後判斷是否滿足步數大於等於k,不滿足的話再回溯破壞別的牆。

#include <bits/stdc++.h>
using namespace std;

const int dir[4][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}};
int n, m, x, y, k;
char mp[10][10];

bool dfs(int xx, int yy, int d)
{
    if (xx == 1 && yy == 1) return d >= k;
    for (int i = 0; i < 4; ++i) {
        int nx = xx + dir[i][0], ny = yy + dir[i][1];
        if (!nx || !ny || nx > n || ny > m || mp[nx][ny] != '*')
            continue;
        int cnt = 0;
        for (int j = 0; j < 4; ++j) {
            int tx = nx + dir[j][0], ty = ny + dir[j][1];
            if (mp[tx][ty] == '.') ++cnt;
        }
        if (cnt > 1) continue;
        mp[nx][ny] = '.';
        if (dfs(nx, ny, d+1)) return 1;
        mp[nx][ny] = '*';
    }
    return 0;
}

int main()
{
    cin >> n >> m >> x >> y >> k;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            mp[i][j] = '*';
    mp[x][y] = '.';
    dfs(x, y, 0);
    for (int i = 1; i <= n; ++i)
        puts(mp[i]+1);
    return 0;
}

EOJ 1888 陸行鳥挖寶


你坐在陸行鳥上進行一個挖寶任務,陸行鳥有三種移動方式,假定移動前的座標爲 X,則:
移動到 2X 的地方。
移動到 X−1 的地方。
移動到 X+1 的地方。
爲了儘快挖到寶物而不至於被別人先挖到,你需要選擇最快的方式挖到寶物。

一開始以爲是dp。。後來發現直接bfs三種情況就好了。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100005;
queue<int> q;
bool vis[maxn];
int step[maxn];

bool judge(int n)
{
    if (n < 0 || n > maxn-5) return 1;
    return 0;
}

int bfs(int s, int e)
{
    q.push(s);
    vis[s] = 1;
    int now, next;
    while (!q.empty()) {
        now = q.front();
        q.pop();
        for (int i = 0; i < 3; ++i) {
            switch(i) {
            case 0: next = now+1; break;
            case 1: next = now-1; break;
            case 2: next = now << 1;
            }
            if (judge(next)) continue;
            if (!vis[next]) {
                step[next] = step[now]+1;
                if (next == e) return step[next];
                vis[next] = 1;
                q.push(next);
            }
        }
    }
}

int main()
{
    int s, e;
    while (cin >> s >> e) {
        memset(vis, 0, sizeof vis);
        if (s >= e) cout << s-e << endl;
        else cout << bfs(s, e) << endl;
    }
    return 0;
}

EOJ 10/Greater New York 2016 Bob and a Binary tree


現有一個無限的完全二叉樹,每個節點上都標有一個有理數。定義如下:
根節點上的有理數是 1/1。
p/q 左兒子節點的標記是 p/(p+q)。
p/q 右兒子節點的標記是 (p+q)/q。
按照從上到下從左到右的順序,可以遍歷得到一個有理數序列:
F(1) = 1/1, F(2) = 1/2, F(3) = 2/1, F(4) = 1/3, F(5) = 3/2, F(6) = 2/3, …
本題任務是給定 n,計算 F(n)。

自底向上,模擬題意來遞歸(好像並不算dfs啊?)。

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ll;

void dfs(ll n, ll &p, ll &q)
{
    if (n == 1) {
        p = 1;
        q = 1;
        return;
    }
    dfs(n>>1, p, q);
    n & 1 ? p += q : q += p;
}

int main()
{
    int cas;
    ll n, p, q;
    cin >> cas;
    for (int t = 1; t <= cas; ++t) {
        scanf("%lld", &n);
        p = q = 0;
        dfs(n, p, q);
        printf("Case %d: %lld/%lld\n", t, p, q);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章