简单搜索 |
深度优先搜索 |
poj2488,poj3083,poj3009,poj1321 |
广度优先搜索 |
poj2251,poj1426,poj3126,poj3087.poj3414 poj 1606 |
|
简单搜索技巧和剪枝 |
poj2531,poj1416,poj2676,poj1129 |
poj 2488
好恶心的题。。。应该用深搜的,我用的bfs,wa掉,改成dfs,还是wa。。。注意向八个方向扩展的顺序,保证输出结果按字典序排列。
int dir[8][2] = { {-2, -1},{-2, 1},{-1, -2},{-1, 2},{1, -2},{1, 2},{2, -1},{2, 1}};
贡献无数wa,T_T
poj 3083
求左优先和右优先的时候用dfs,注意顺序。
int Left[4][2] = { {1, 0}, {0, -1}, {-1, 0}, {0, 1}};
int Right[4][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1}};
1 #include
2 #include
3 #include
4 #include
5
6 using namespace std;
7
8 const int N = 100;
9
10 struct node {
11 int x;
12 int y;
13 int s;
14 } q[100000];
15
16 char mp[N][N];
17 int vis[N][N];
18 int w, h, dir;
19 int si, sj, ei, ej;
20
21 int Left[4][2] = { { 1, 0}, { 0, -1}, {-1, 0}, { 0, 1}};
22 int Right[4][2] = { { 1, 0}, { 0, 1}, {-1, 0}, { 0, -1}};
23
24 bool inMap(int x, int y) {
25 if(x < 0 || x >= h || y < 0 || y >= w) return false;
26 return true;
27 }
28
29 int dfs_l(int x, int y, int s) {
30 if(x == ei && y == ej) {
31 return s + 1;
32 }
33 if(!inMap(x, y) || mp[x][y] == '#') return 0;
34 dir = (dir + 3) % 4;
35 int tmp;
36 while(1) {
37 tmp = dfs_l(x + Left[dir][0], y + Left[dir][1], s + 1);
38 if(tmp > 0) break;
39 dir = (dir + 1) % 4;
40 }
41 }
42
43 int dfs_r(int x, int y, int s) {
44 if(x == ei && y == ej) {
45 return s + 1;
46 }
47 if(!inMap(x, y) || mp[x][y] == '#') return 0;
48 dir = (dir + 3) % 4;
49 int tmp;
50 while(1) {
51 tmp = dfs_r(x + Right[dir][0], y + Right[dir][1], s + 1);
52 if(tmp > 0) break;
53 dir = (dir + 1) % 4;
54 }
55 }
56
57 int bfs() {
58 int f = 0, r = 0, i;
59 node u, v;
60 q[r].x = si; q[r].y = sj; q[r++].s = 0;
61 vis[si][sj] = true;
62
63 while(f < r) {
64 u = q[f++];
65 if(u.x == ei && u.y == ej) return u.s + 1;
66 for(i = 0; i < 4; ++i) {
67 v.x = u.x + Left[i][0];
68 v.y = u.y + Left[i][1];
69 v.s = u.s + 1;
70 if(inMap(v.x, v.y) && !vis[v.x][v.y] && mp[v.x][v.y] != '#') {
71 vis[v.x][v.y] = true;
72 q[r++] = v;
73 }
74 }
75 }
76 return 0;
77 }
78
79 int main() {
80 //freopen("data.in", "r", stdin);
81
82 int t, i, j, l, r;
83 scanf("%d", &t);
84 while(t--) {
85 scanf("%d%d", &w, &h);
86
87 for(i = 0; i < h; ++i) {
88 scanf("%s", mp[i]);
89 for(j = 0; j < w; ++j) {
90 if(mp[i][j] == 'S') {
91 si = i; sj = j;
92 }
93 if(mp[i][j] == 'E') {
94 ei = i; ej = j;
95 }
96 }
97 }
98 memset(vis, 0, sizeof(vis));
99 dir = 0;
100 l = dfs_l(si, sj, 0);
101 dir = 0;
102 r = dfs_r(si, sj, 0);
103 printf("%d %d %d\n", l, r, bfs());
104 }
105 return 0;
106 }
poj 1321
f(i, k)表示一颗棋子至少应该放在第i行,并且当前共有k个棋子要放。
0 <= i <= n - k
f(i, k) = f(i + 1, k)(这一行不放,还有剩k个要放) + sum(f(i + 1, k - 1))(这一行放,枚举列数累加下一行可放的情况数)
1 res += dfs(r + 1, k);
2 for(i = 0; i < n; ++i) {
3 if(mp[r][i] == '#' && !cm[i] && !rm[r]) {
4 cm[i] = true; rm[r] = true;
5 res += dfs(r + 1, k - 1);
6 cm[i] = false; rm[r] = false;
7 }
8 }
poj 2251
三维的搜索题,直接写bfs。跟HDU_1253 胜利大逃亡(BFS)
一样的题。。。话说,这两天来终于1A一次了. =_=///
渣代码:
1 #include
2 #include
3 #include
4 #include
5
6 using namespace std;
7
8 const int N = 33;
9
10 class node {
11 public:
12 int y, x;
13 int l, t;
14
15 bool indung();
16 bool operator == (const node & c) {
17 return (l == c.l && x == c.x && y == c.y);
18 }
19 } q[100000];
20
21 node s, e;
22 int le, rl, cw;
23 char mp[N][N][N];
24 bool vis[N][N][N];
25
26 int dir[6][3] = { { 1, 0, 0}, {-1, 0, 0}, { 0, 1, 0},
27 { 0, -1, 0}, { 0, 0, -1}, { 0, 0, 1}};
28
29
30 bool node::indung() {
31 if(l >= 0 && l < le) {
32 if(x >= 0 && x < rl) {
33 if(y >= 0 && y < cw) return true;
34 }
35 }
36 return false;
37 }
38
39 int bfs() {
40 int f = 0, r = 0, i;
41 q[r++] = s;
42 memset(vis, 0, sizeof(vis));
43 vis[s.l][s.x][s.y] = true;
44 node u, v;
45 while(f < r) {
46 u = q[f++];
47 if(u == e) return u.t;
48
49 for(i = 0; i < 6; ++i) {
50 v.l = u.l + dir[i][0];
51 v.x = u.x + dir[i][1];
52 v.y = u.y + dir[i][2];
53 v.t = u.t + 1;
54 if(v.indung() && !vis[v.l][v.x][v.y] && mp[v.l][v.x][v.y] != '#') {
55 vis[v.l][v.x][v.y] = true;
56 q[r++] = v;
57 }
58 }
59 }
60 return -1;
61 }
62
63 int main() {
64 //freopen("data.in", "r", stdin);
65
66 int i, j, k, ans;
67 while(~scanf("%d%d%d", &le, &rl, &cw)) {
68 if(!le && !rl && !cw) break;
69
70 for(i = 0; i < le; ++i) {
71 for(j = 0; j < rl; ++j) {
72 scanf("%s", mp[i][j]);
73 for(k = 0; k < cw; ++k) {
74 if(mp[i][j][k] == 'S') {
75 s.l = i; s.x = j; s.y = k; s.t = 0;
76 }
77 if(mp[i][j][k] == 'E') {
78 e.l = i; e.x = j; e.y = k; e.t = 0;
79 }
80 }
81 }
82 }
83 ans = bfs();
84 if(ans < 0) puts("Trapped!");
85 else {
86 printf("Escaped in %d minute(s).\n", ans);
87 }
88 }
89 return 0;
90 }
poj 1426
题意是给一个n,求一个十进制数m。满足m仅由0, 1组成。还好这个是个Special Judge,思路是从1开始,每次左移一位(后边补0)判断移位后和移位+1后能否整除n。记录每种状态bfs
ps: 没写头文件
poj 3126
数据很水,本菜的暴力bfs没加任何剪枝,居然0ms过了。刚开始素数表打错了。wa了一次,检讨!
代码有点shi。。。
#include
#include
#include
#include <string>
using namespace std;
const int N = 10010;
struct node {
int x;
int t;
} q[100000];
int prim[N];
int base[4] = { 1, 10, 100, 1000};
int s, e;
bool vis[N];
void init() {
int i, j;
memset(prim, true, sizeof(prim));
for(i = 2; i < 10000; ++i) {
for(j = 2; j < 10000; ++j) {
if(i *j > 10000) break;
prim[i*j] = false;
}
}
}
int bfs() {
int f = 0, r = 0, i, tmp;
node u, v;
u.x = s; u.t = 0;
q[r++] = u;
memset(vis, false, sizeof(vis));
vis[s] = true;
int x1, x2, x3, x4;
while(f < r) {
u = q[f++];
if(u.x == e) return u.t;
x1 = u.x % 10;
x2 = u.x % 100 - x1;
x3 = u.x % 1000 - x2 - x1;
x4 = u.x - x3 - x2 - x1;
//printf("%d %d %d %d\n", x1, x2, x3, x4);
//1
tmp = x4 + x3 + x2;
for(i = 1; i < 10; ++i) {
v.x = tmp + (i);
if(v.x == u.x) continue;
if(prim[v.x] && !vis[v.x]) {
vis[v.x] = true;
v.t = u.t + 1;//printf("%d %d\n", v.x, v.t);
q[r++] = v;
}
}
//10
tmp = x4 + x3 + x1;
for(i = 0; i < 10; ++i) {
v.x = tmp + (i*10);
if(v.x == u.x) continue;
if(prim[v.x] && !vis[v.x]) {
vis[v.x] = true;
v.t = u.t + 1;//printf("%d %d\n", v.x, v.t);
q[r++] = v;
}
}
//100
tmp = x4 + x2 + x1;
for(i = 0; i < 10; ++i) {
v.x = tmp + (i*100);
if(v.x == u.x) continue;
if(prim[v.x] && !vis[v.x]) {
vis[v.x] = true;
v.t = u.t + 1;//printf("%d %d\n", v.x, v.t);
q[r++] = v;
}
}
//1000
tmp = x3 + x2 + x1;
for(i = 1; i < 10; ++i) {
v.x = tmp + (i*1000);
if(v.x == u.x) continue;
if(prim[v.x] && !vis[v.x]) {
vis[v.x] = true;
v.t = u.t + 1;//printf("%d %d\n", v.x, v.t);
q[r++] = v;
}
}
}
return -1;
}
int main() {
//freopen("data.in", "r", stdin);
//freopen("data.out", "w", stdout);
int t, ans;
scanf("%d", &t);
init();
while(t--) {
scanf("%d%d", &s, &e);
ans = bfs();
cout << ans << endl;
}
return 0;
}
poj 3414
bfs,回溯输出路径。 (poj 1606相同)
1 #include
2 #include
3 #include
4 #include
5
6 using namespace std;
7
8 const int N = 110;
9
10 struct node {
11 int potA;
12 int potB;
13 int pre;
14 int stp;
15 int flg;
16 } q[100000];
17
18 bool vis[N][N];
19 int A, B, C;
20
21 void dfs(int p) {
22 if(q[p].pre == -1) return ;
23 dfs(q[p].pre);
24
25 switch(q[p].flg) {
26 case 0: puts("FILL(1)"); break;
27 case 1: puts("DROP(1)"); break;
28 case 2: puts("POUR(2,1)"); break;
29 case 3: puts("FILL(2)"); break;
30 case 4: puts("DROP(2)"); break;
31 case 5: puts("POUR(1,2)"); break;
32 }
33
34 }
35
36 void potA(node& v, node u, int& r) {
37 //fill
38 v.potA = A; v.potB = u.potB; v.flg = 0;
39 if(!vis[v.potA][v.potB]) {
40 vis[v.potA][v.potB] = true;
41 q[r++] = v;
42 }
43 //drop
44 v.potA = 0; v.potB = u.potB; v.flg = 1;
45 if(!vis[v.potA][v.potB]) {
46 vis[v.potA][v.potB] = true;
47 q[r++] = v;
48 }
49 //pour
50 v.flg = 2;
51 if(u.potB <= A - u.potA) {
52 v.potB = 0;
53 v.potA = u.potA + u.potB;
54 } else {
55 v.potB = u.potB - (A - u.potA);
56 v.potA = A;
57 }
58 if(!vis[v.potA][v.potB]) {
59 vis[v.potA][v.potB] = true;
60 q[r++] = v;
61 }
62 }
63
64 void potB(node& v, node u, int& r) {
65 //fill
66 v.potB = B; v.potA = u.potA; v.flg = 3;
67 if(!vis[v.potA][v.potB]) {
68 vis[v.potA][v.potB] = true;
69 q[r++] = v;
70 }
71 //drop
72 v.potB = 0; v.potA = u.potA; v.flg = 4;
73 if(!vis[v.potA][v.potB]) {
74 vis[v.potA][v.potB] = true;
75 q[r++] = v;
76 }
77 //pour
78 v.flg = 5;
79 if(u.potA <= B - u.potB) {
80 v.potA = 0;
81 v.potB = u.potB + u.potA;
82 } else {
83 v.potA = u.potA - (B - u.potB);
84 v.potB = B;
85 }
86 if(!vis[v.potA][v.potB]) {
87 vis[v.potA][v.potB] = true;
88 q[r++] = v;
89 }
90 }
91
92 void bfs() {
93 int f = 0, r = 0;
94 node u, v;
95 u.potA = u.potB = 0;
96 u.pre = -1; u.stp = 0;
97 q[r++] = u;
98 memset(vis, 0, sizeof(vis));
99 vis[0][0] = true;
100
101 while(f < r) {
102 u = q[f++];
103 if(u.potA == C || u.potB == C) {
104 printf("%d\n", u.stp);
105 dfs(f-1);
106 return ;
107 }
108 v.stp = u.stp + 1;
109 v.pre = f-1;
110 potA(v, u, r);
111 potB(v, u, r);
112
113 }
114 puts("impossible");
115 }
116
117 int main() {
118 //freopen("data.in", "r", stdin);
119
120 while(~scanf("%d%d%d", &A, &B, &C)) {
121 bfs();
122 }
123 return 0;
124 }
poj 2531
在discuss里看到有一种随机算法。貌似有些题目是可以用这种方法解的,比如Miller-Rabin测试,Pollard-rho因式分解都是概率型的。当数据不是很强时还是很值得用的。
1 #include
2 #include
3 #include
4 #include
5 #include
6
7 using namespace std;
8
9 const int N = 50;
10 const int RAND = 100000;
11
12 bool sub[N];
13 int mp[N][N];
14 int n;
15
16 int solve() {
17 int i, j, t, sum = 0, res = 0;
18 memset(sub, 0, sizeof(sub));
19
20 for(i = 0; i < RAND; ++i) {
21 t = rand()%n;
22 sub[t] = !sub[t];
23 for(j = 0; j < n; ++j) {
24 if(sub[j] == sub[t]) {
25 sum -= mp[j][t];
26 } else {
27 sum += mp[j][t];
28 }
29 }
30 res = max(sum, res);
31 }
32 return res;
33 }
34
35 int main() {
36 //freopen("data.in", "r", stdin);
37
38 int i, j;
39 while(~scanf("%d", &n)) {
40 for(i = 0; i < n; ++i) {
41 for(j = 0; j < n; ++j) {
42 scanf("%d", &mp[i][j]);
43 }
44 }
45 printf("%d\n", solve());
46 }
47 return 0;
48 }
POJ 1129
图的着色问题。暴力回溯。详见:http://blog.csdn.net/suwei19870312/article/details/5282932