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