SCUT ACM PLACTICE # 3 二进制枚举,深搜,广搜

来源:互联网 发布:淘宝名鞋库 编辑:程序博客网 时间:2024/05/16 01:21

Links:https://vjudge.net/contest/145674#overview


A - 搜索 初心者向 HDU - 2553

简单搜索n皇后,主要是要处理判断是否能放置的问题。
这次我用了四个数组来判断行,列,主对角和副对角是否已经有棋子。

#include<iostream>#include<string.h>#include<string>#include<math.h>#include<stdio.h>using namespace std;int n;bool h[50], l[50], z[50], f[50];int ans[15];int dfs(int x, int y){    if (y == n){ return 1; }    int ans = 0;    h[x] = 1, l[y] = 1, z[x + y] = 1, f[x - y + 20] = 1;    for (int i = 1; i <= n; i++){        if (h[i] == 0 && l[y + 1] == 0 && z[i + y + 1] == 0 && f[i - y - 1 + 20] == 0){            ans += dfs(i, y + 1);        }    }    h[x] = 0, l[y] = 0, z[x + y] = 0, f[x - y + 20] = 0;    return ans;}int main(){    for (int i = 1; i <= 10; i++){        for (int j = 1; j <= i; j++){            n = i;            ans[i] += dfs(j, 1);        }    }    while (~scanf("%d", &n),n!=0){        printf("%d\n", ans[n]);    }    return 0;}

B - 搜索 中级者向 POJ - 3278

广搜,能够对当前数字+1,-1,*2,求最小步骤从初始数字到终末数字。

#include<iostream>#include<string.h>#include<string>#include<stdio.h>#include<queue>using namespace std;int fx, fy;int astep;int v[300005];struct point{    int x;    int s;}beg;queue<point> que;int bfs(){    int ans = -1;    int k = fy > fx ? (fy - fx) : (fx - fy);    while (!que.empty()){        point cnt = que.front();        que.pop();        if (astep != -1 && cnt.s > astep||cnt.x<0||cnt.x>105000||cnt.s>k){ continue; }        if (cnt.x == fy){             if (astep == -1){ astep = cnt.s; }            else{ astep = astep < cnt.s ? astep : cnt.s; }            continue; }        if (v[cnt.x + 1] == 0){            que.push({ cnt.x + 1, cnt.s + 1 });            v[cnt.x + 1] = 1;        }        if (cnt.x-1>=0&&v[cnt.x - 1] ==0){            que.push({ cnt.x - 1, cnt.s + 1 });            v[cnt.x -1] = 1;            }        if (cnt.x != 0 && v[cnt.x * 2] == 0){            que.push({ cnt.x * 2, cnt.s + 1 });             v[cnt.x*2] = 1; }    }    return ans;}int main(){    scanf("%d%d", &fx, &fy);    astep = -1;    beg.x = fx, beg.s = 0;    que.push(beg);    bfs();    printf("%d",astep );    return 0;}

C - 搜索 中级者向 POJ - 2488

八方向跳棋,求最终整个棋盘都跳满的路径,要求输出路径比较麻烦,dfs过程中在相应的格子记录上这是跳的第几步就行了。

#include<iostream>#include<string.h>#include<string>#include<algorithm>#include<stdio.h>using namespace std;int fx, fy,total;bool r;int v[24][24];int dx[8] = {-1,1,-2,2,-2,2,-1,1};int dy[8] = {-2,-2,-1,-1,1,1,2,2};void dfs(int x,int y,int n){    if (r == false)    v[x][y] = n;    if (n == total){        r = true; return; }    for (int i = 0; i < 8; i++){        int nx = x + dx[i], ny = y + dy[i];        if (nx>0 && nx <= fx&&ny > 0 && ny <= fy&&v[nx][ny] == 0&&r==false){            dfs(nx, ny, n + 1);            if (r == true){ break; }        }    }       if (r==false)    v[x][y] = 0;}void pf(int x, int y,int n){    putchar(y + 64);    printf("%d", x);    if (n == total){ return; }    for (int i = 0; i < 8; i++){        if (v[x + dx[i]][y + dy[i]] == n + 1){            pf(x + dx[i], y + dy[i], n + 1);        }    }}int main(){    int t;    scanf("%d", &t);    for(int k=1;k<=t;k++){        int ax, ay;        r = false;        memset(v, 0, sizeof(v));        scanf("%d%d", &fx, &fy);        total = fx*fy;        for (int i = 1; i <= fx; i++){            for (int j = 1; j <= fy; j++){                dfs(i, j,1);                if (r == true){                    ax = i, ay = j;                    break; }            }            if (r == true)break;        }        printf("Scenario #%d:\n", k);        if (r == false){ printf("impossible\n\n"); }        else{            pf(ax, ay,1);            printf("\n\n");        }    }    return 0;}

D - 搜索 初心者向

三维地图bfs最短路径,方向变成6个。

#include<iostream>#include<string.h>#include<string>#include<stdio.h>#include<queue>using namespace std;int l, r, c,ans;int map[32][32][32];bool v[32][32][32];int dl[6] = { 0, 0, 0, 0, 1, -1 };int dx[6] = { -1, 0, 0, 1, 0, 0 };int dy[6] = { 0, -1, 1, 0, 0, 0 };struct point{    int l;    int x;    int y;    int s;}beg;queue<point> que;int bfs(){    int ans = -1;    while (!que.empty()){        point cnt = que.front();        que.pop();        if (map[cnt.l][cnt.x][cnt.y]=='E'){ ans = cnt.s; break; }        for (int i = 0; i < 6; i++){            point np={ cnt.l + dl[i], cnt.x + dx[i], cnt.y + dy[i], cnt.s + 1 };            if (np.l >= 0 && np.l<l&&np.x>=0 && np.x<r&&np.y>=0 && np.y < c){                if (map[np.l][np.x][np.y] != '#'&&v[np.l][np.x][np.y]==0){                    que.push(np);                    v[np.l][np.x][np.y] = 1;                }            }        }    }    while (!que.empty()){        que.pop();    }    return ans;}int main(){    while (scanf("%d%d%d", &l, &r, &c)){        memset(v, 0, sizeof(v));        getchar();        if (l == 0){ return 0; }        for (int i = 0; i < l; i++){            for (int j = 0; j < r; j++){                for (int k = 0; k < c; k++){                    map[i][j][k]=getchar();                    if (map[i][j][k] == 'S'){                        beg.l = i, beg.x = j, beg.y = k,beg.s=0;                        v[i][j][k] = 1;                    }                }                getchar();            }            getchar();        }        que.push(beg);        int ans = bfs();        if (ans == -1){            printf("Trapped!\n");        }        else{            printf("Escaped in %d minute(s).\n",ans);        }    }    return 0;}

E - 搜索(DFS) 初心者向

连通块计数,经典的dfs

#include<iostream>#include<string.h>#include<string>#include<math.h>#include<stdio.h>using namespace std;int n, m;char map[105][105];int dx[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };int dy[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };void dfs(int x, int y){    map[x][y] = '.';    for (int i = 0; i < 8; i++){        int nx = x + dx[i], ny = y + dy[i];        if (nx >= 0 && nx < n&&ny >= 0 && ny < m&&map[nx][ny] == 'W'){            dfs(nx, ny);        }    }}int main(){    scanf("%d%d", &n, &m);    for (int i = 0; i < n; i++){        getchar();        for (int j = 0; j < m; j++){            map[i][j] = getchar();        }    }    int ans = 0;    for (int i = 0; i < n; i++){        for (int j = 0; j < m; j++){            if (map[i][j] == 'W'){                dfs(i, j);                ans++;            }        }    }    printf("%d", ans);    return 0;}

F - 搜索(BFS)+模拟 中级者向 POJ - 3083

给出地图求三种走法的路径:左扶墙,右扶墙,最短路。

#include<iostream>#include<string.h>#include<string>#include<stdio.h>#include<queue>using namespace std;int fx, fy;char map[45][45];bool v[45][45];int dx1[4] = { 0, -1, 0, 1, };int dy1[4] = { 1, 0, -1, 0, };int dx2[4] = { 0, -1, 0, 1, };int dy2[4] = { -1, 0, 1, 0, };struct point{    int x;    int y;    int s;}beg;queue<point> que;int bfs(){    int ans = -1;    while (!que.empty()){        point cnt = que.front();        que.pop();        if (map[cnt.x][cnt.y] == 'E'){ ans = cnt.s; break; }        for (int i = 0; i < 4; i++){            point np = { cnt.x + dx1[i], cnt.y + dy1[i], cnt.s + 1 };            if (np.x >= 0 && np.x<fx&&np.y >= 0 && np.y < fy){                if (map[np.x][np.y] != '#'&&v[np.x][np.y] == 0){                    que.push(np);                    v[np.x][np.y] = 1;                }            }        }    }    while (!que.empty()){        que.pop();    }    return ans;}int dfs(point cnt,int dir){    if (map[cnt.x][cnt.y] == 'E'){        return cnt.s;    }    for (int i = dir-1;; i++){        int ci = i < 0 ? i + 4:i;        point newp = { cnt.x + dx1[ci % 4], cnt.y + dy1[ci % 4], cnt.s + 1 };        if (newp.x >= 0 && newp.x < fx&&newp.y >= 0 && newp.y < fy&&map[newp.x][newp.y] != '#'){            dfs(newp, i);            break;        }    }}int idfs(point cnt, int dir){    if (map[cnt.x][cnt.y] == 'E'){        return cnt.s;    }    for (int i = dir-1;; i++){        int ci = i < 0 ? i + 4 : i;        point newp = { cnt.x + dx2[ci % 4], cnt.y + dy2[ci % 4], cnt.s + 1 };        if (newp.x >= 0 && newp.x < fx&&newp.y >= 0 && newp.y < fy&&map[newp.x][newp.y] != '#'){            idfs(newp, i);            break;        }    }}int main(){    int t;    scanf("%d", &t);    while (t--){        scanf("%d%d", &fy, &fx);        memset(v, 0, sizeof(v));        getchar();        for (int i = 0; i < fx; i++){            for (int j = 0; j < fy; j++){                map[i][j] = getchar();                if (map[i][j] == 'S'){                    beg.x = i, beg.y = j, beg.s = 1;                    v[i][j] = 1;                }            }            getchar();        }        que.push(beg);        int ans = bfs();        int ans1 = dfs(beg,0);        int ans2 = idfs(beg, 0);        printf("%d %d %d\n", ans2, ans1, ans);    }    return 0;}

G - 欧拉图 初心者向 HDU - 1878

判断欧拉回路的题。并查集判连通。

#include<iostream>#include<string.h>#include<string>#include<stdio.h>using namespace std;int n, m;int point[1005];int f[1005];int F(int x){    if (f[x] == x)return x;    else{ return f[x] = F(f[x]); }}int main(){    int x, y;    while (~scanf("%d", &n)){        if (n == 0){ return 0; }        scanf("%d", &m);        for (int i = 1; i <= n; i++){            f[i] = i;        }        memset(point, 0, sizeof(point));        for (int j = 0; j < m; j++){            scanf("%d%d", &x, &y);            point[x]++;            point[y]++;            f[F(x)] = F(y);        }        int ji = 0;        int ff = F(1);        for (int i = 1; i <= n; i++){            if ((point[i] % 2) != 0||F(i)!=ff){                ji = 1; break;            }        }        if (ji == 0){ printf("%d\n",1); }        else{ printf("%d\n",0); }    }    return 0;}

H - 欧拉图 中级者向 POJ - 2230

就是输出一条欧拉回路。

#include <iostream>#include <algorithm>#include <vector>#include <string>#include <stdio.h>using namespace std;#define maxn 50000+10int n, m;struct Edge{    int to;    bool vis;};vector<Edge>G[maxn];void euler(int u){    int num = G[u].size();    for (int i = 0; i < num; i++){        if (G[u][i].vis == 0){            G[u][i].vis = 1;            euler(G[u][i].to);        }    }    printf("%d\n", u);}int main(){    scanf("%d%d", &n, &m);    int x, y;    for (int i = 0; i < m; i++){        scanf("%d%d", &x, &y);        Edge a = { y, 0 };        Edge b = { x, 0 };        G[x].push_back(a);        G[y].push_back(b);    }        euler(1);    return 0;}

I - 欧拉图 上级者向 POJ - 1780

要求把所有可能的密码已最短长度也就是最大的重叠度输出出来,对于n位的密码,答案每往后输出一位,就会与前n-1位构成一个新密码,转换成以n-1位数字为点的欧拉回路,因为除了最后n-1位,一但有一个n-1位数字后面新增0-9都已经在前面输出过了,那么就无法只新增一位来构造一个新密码。
要求非递归,看了别人的代码看了好久才看懂。

#include<cstdio>#include<cstring>#include<queue>using namespace std;int n, ppow[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };int cnt[1000000], stack[1000010];bool vis[1000000];void dfs(){    memset(vis, 0, sizeof(vis));//  vis[0] = 1;    memset(cnt, 0, sizeof(cnt));    int top = -1;    stack[++top] = 0;    int total = ppow[n];    while (top!=total){        int v = stack[top];        if (cnt[v] ==10 ){            vis[v] = 0; cnt[v] = 0;            top--;            continue;        }        int newn = (v * 10 + cnt[v]) % ppow[n];        cnt[v]++;        if (vis[newn]){ continue; }        vis[newn] = 1;        stack[++top] = newn;    }    for (int i = 1; i <= top; ++i) putchar(stack[i] % 10 + '0');}int main(){    while (~scanf("%d", &n) && n){        for (int i = 1; i<n; ++i) putchar('0');        dfs();        putchar('\n');    }    return 0;}

J - 二叉树 中级者向

给出二叉树的前序中序遍历,要求给出后序遍历的结果。分治递归就行。

#include <iostream>#include <algorithm>#include <vector>#include <string>#include <stdio.h>using namespace std;int n;int pre[1005];int in[1005];int cou,acount;void findans(int beg, int end){    if (beg == end){        return;    }    int cnt = pre[cou++];    int mid;    for (int i = beg; i < end; i++){        if (in[i] == cnt){            mid = i;            break;        }    }    findans(beg, mid);    findans(mid + 1, end);    printf("%d", in[mid]);    if (acount <n-1){ printf(" "); }    acount++;}int main(){    while (~scanf("%d", &n)){        cou = 0,acount=0;        for (int i = 0; i < n; i++){            scanf("%d", &pre[i]);        }        for (int i = 0; i < n; i++){            scanf("%d", &in[i]);        }        findans(0, n );        printf("\n");    }}

K - 二进制枚举 初心者向

输出比给定数字大的只包含4和7且4和7的数量相等的最小数字,枚举每一位是4或7就行。

#include<iostream>#include<string.h>#include<string>#include<stdio.h>using namespace std;long long num;long long ans;void dfs(long long n,int fn,int sn){    if (ans!=0&&n >ans||n>num*100 ){ return; }    if (fn == sn&&n>=num){         if (ans == 0){ ans = n; }        else{ ans = ans < n ? ans : n; }    }    dfs(n * 10 + 4,fn+1,sn);    dfs(n * 10 + 7,fn,sn+1);}int main(){    while (cin >> num){        ans = 0;        dfs(0, 0, 0);        cout << ans << endl;    }    return 0;}

L - 二进制枚举 初心者向 HDU - 1557

简单的枚举题。

#include<iostream>#include<string.h>#include<stdio.h>using namespace std;int n;int p;int v[25];int dfs(int x, int y,int num){    if (y == n-1){        if (num > p && (num - v[x] <= p)){ return 1; }        else {return 0;}    }    int ans = 0;    if (y+1 == x){        ans += dfs(x, y + 1, num + v[y+1]);    }    else{        ans += dfs(x, y + 1, num);        ans += dfs(x, y + 1, num + v[y+1]);    }    return ans;}int main(){    int t;    cin >> t;    while (t--){        int total = 0;        cin >> n;        for (int i = 0; i < n; i++){            cin >> v[i];            total += v[i];        }        p = total / 2;        for (int i = 0; i < n; i++){            cout << dfs(i, -1, 0);            if (i < n - 1){ cout << " "; }        }        cout << endl;    }    return 0;}

M - 二进制枚举 初心者向 CodeForces - 202A

求字典序最大的回文字串。

#include<iostream>#include<string.h>#include<string>#include<stdio.h>using namespace std;string raw, ans;int length;bool pal(string a){    int len = a.length();    bool ans = true;    for (int i = 0; i < len / 2; i++){        if (a[i] != a[len - i - 1]){            ans = false;            break;        }    }    return ans;}void dfs(int x,string cnt){    if (pal(cnt)){        if (ans == " "||cnt>ans){            ans = cnt;        }    }    if (x == length - 1){ return; }    dfs(x + 1, cnt + raw[x + 1]);    dfs(x + 1, cnt);}int main(){    cin >> raw;    ans = " ";    length = raw.length();    dfs(-1, "");    cout << ans;    return 0;}
0 0
原创粉丝点击