PAT甲级—暴力搜索

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);
}
Segmentation Fault(DFS)
#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);
}
Accepted(BFS)

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");
}
View Code

 

posted @ 2021-01-28 11:23  sparkyen  阅读(94)  评论(0编辑  收藏  举报