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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章