1.BFS
1091 Acute Stroke (30point(s))
基础的搜索,但是直接用递归会导致段错误,改用队列之后就不会了,这说明递归调用在空间利用率上还是很吃亏的。
#include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <cmath> #include <map> #include <queue> #include <vector> #include <set> #define ll long long #define inf 0x3f3f3f #define pii pair<int, int> #define pb push_back using namespace std; const int maxn = 1e5+100; int n, m, l, t; int cnt, res, mp[70][200][1500]; bool vis[70][200][1500]; void dfs(int x, int y, int z){ if(x<1||x>l||y<1||y>n||z<1||z>m||mp[x][y][z]!=1||vis[x][y][z]) return; vis[x][y][z] = 1, cnt++; dfs(x+1, y, z), dfs(x, y+1, z), dfs(x, y, z+1); dfs(x-1, y, z), dfs(x, y-1, z), dfs(x, y, z-1); return; } int main(){ scanf("%d%d%d%d", &n, &m, &l, &t); for(int i = 1; i <= l; i++) for(int j = 1; j <= n; j++) for(int k = 1; k <= m; k++) scanf("%d", &mp[i][j][k]); for(int i = 1; i <= l; i++){ for(int j = 1; j <= n; j++){ for(int k = 1; k <= m; k++){ if(mp[i][j][k]==1&&!vis[i][j][k]) { dfs(i, j, k); if(cnt>=t) res += cnt; cnt = 0; } } } } printf("%d", res); }
#include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <cmath> #include <map> #include <queue> #include <vector> #include <set> #define ll long long #define inf 0x3f3f3f #define pii pair<int, int> #define pb push_back using namespace std; const int maxn = 1e5+100; struct node{ int x, y, z; }; int n, m, l, t; int cnt, res, mp[70][200][1500]; bool vis[70][200][1500]; void bfs(int x, int y, int z){ queue<node> que; que.push({x, y, z}); int cnt = 0; while(!que.empty()){ node tmp = que.front(); que.pop(); int x = tmp.x, y = tmp.y, z = tmp.z; if(x<1||x>l||y<1||y>n||z<1||z>m||mp[x][y][z]!=1||vis[x][y][z]) continue; vis[x][y][z] = 1, cnt++; que.push({x+1, y, z}), que.push({x, y+1, z}), que.push({x, y, z+1}); que.push({x-1, y, z}), que.push({x, y-1, z}), que.push({x, y, z-1}); } if(cnt>=t) res += cnt; } int main(){ scanf("%d%d%d%d", &n, &m, &l, &t); for(int i = 1; i <= l; i++) for(int j = 1; j <= n; j++) for(int k = 1; k <= m; k++) scanf("%d", &mp[i][j][k]); for(int i = 1; i <= l; i++) for(int j = 1; j <= n; j++) for(int k = 1; k <= m; k++) if(mp[i][j][k]==1&&!vis[i][j][k]) bfs(i, j, k); printf("%d", res); }
Reference:
https://github.com/LNoving/PAT
2.DFS
1103 Integer Factorization (30分)
这题就是DFS+剪枝,剪枝不够的话有几个测试样例会超时,主要体现在:
- 需要事先把各个数的p次方求出来并保存在数组中,避免后面在DFS中反复计算
- 各项的幂数相同,系数必然会形成排列,可以规定序列为降序,避免出现像3 2 4 1和2 4 3 1这样重复搜索的情况。进一步我们可以限制选取当前项系数的上下界,上限可以设置为上一项的系数值,下限可以通过判断最后能不能用完num来判断
怎么也没想到这题调试了一下午,最开始没用vector而是用的string,可能因为不那么熟悉string,出现了各种小问题比如初始化之类的,光在这个上面就百度了很久,惭愧。后来发现别人用的vector,就赶紧用这个改了一遍就好了,后面就是超时再优化的问题了
#include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <cmath> #include <map> #include <queue> #include <vector> #include <set> #define ll long long #define inf 0x3f3f3f #define pii pair<int, int> #define pb push_back using namespace std; // const int maxn = 1e5+100; int n, k, p; int cnt, sum, fac[400]; //string s("", 400), res("", 400); vector<int> now, res; int qpow(int a, int n){ int res = 1; while(n){ if(n&1) res *= a; a *= a; n >>= 1; } return res; } void init(){ for(int i = 0; i <= sqrt(n); i++) fac[i] = qpow(i, p); } void dfs(int num, int id){ if(id>k) return; else if(num==0&&id==k) { if(cnt>sum) res = now, sum = cnt; else if(cnt==sum) res = max(res, now); return; } int r = id > 0 ? now[id-1] : pow(num, 1.0/p); for(int i = r; i >= 1; i--){ if((k-id+1)*fac[i] < num) break; else if(num-fac[i]<0) continue; now.pb(i), cnt += i; dfs(num-fac[i], id+1); now.pop_back(), cnt -=i; } } int main(){ scanf("%d%d%d", &n, &k, &p); init(), dfs(n, 0); if(!res.empty()){ printf("%d = %d^%d", n, res[0], p); for(int i = 1; i <= k-1; i++) printf(" + %d^%d", res[i], p); } else printf("Impossible"); }