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;
}