第一周刷题总结(9.5~9.9)

POJ——1321

 题意:在矩阵特定区域放置k个棋子有多少种放法

题解:dfs,从第一行开始

#include<iostream>
#include<string>
using namespace std;
char a[9][9];
int cl[9];
int n, k, ans;
void dfs(int r, int num)
{
    if (num == k) {
        ans++;
        return;
    }
    if (r > n)
        return;
    int i;
    for (i = 1; i <= n; i++) {
        if (a[r][i] == '#' && cl[i] == 0) {
            cl[i] = 1;
            dfs(r + 1, num + 1);
            cl[i] = 0;
        }
    }
    dfs(r + 1, num);
}
int main()
{

    while (~scanf_s("%d%d", &n, &k)) {
        if (n == -1 && k == -1)
            break;
        getchar();
        int i, j;
        for (i = 1; i <= n; i++) {
            for (j = 1; j <= n; j++)
                cin >> a[i][j];
        }
        memset(cl, 0, sizeof(cl));
        ans = 0;
        dfs(1, 0);
        cout << ans << endl;
    }
    return 0;
}

POJ——2251

题意:在三维迷宫中找到从起点‘S’到终点‘E’的最短路径

题解:建立三维数组,bfs

#include <iostream>
#include<queue>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
#define maxn 31
char a[maxn][maxn][maxn];
int d[maxn][maxn][maxn];
int dir[6][3]={{-1,0,0},{1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};//2向右3向左4向上
int sum=0;
int L,R,C;
struct node{
int x,y,z;
};
node start,ed;
int  bfs()
{
    queue<node> Q;
    Q.push(start);
    node cur;
     node next;
    while(Q.size())
    {
        cur=Q.front();
        Q.pop();
            for(int i=0;i<6;i++)
            {
                next.x=cur.x+dir[i][0];
                next.y=cur.y+dir[i][1];
                next.z=cur.z+dir[i][2];
                if(next.x>=0&&next.x<R&&next.y>=0&&next.y<C&&next.z>=0&&next.z<L&&a[next.z][next.x][next.y]!='#'&&d[next.z][next.x][next.y]==0)
                {
                    //a[cur.z][cur.x][cur.y]='#';  这样操作的话在栈中的点,也有可能到达当前的next点,
                    //若用d[next.z][next.x][next.y]==0判断,只要到达next,就不会再判断
                    d[next.z][next.x][next.y]=d[cur.z][cur.x][cur.y]+1;
                     if(next.x==ed.x&&next.y==ed.y&&next.z==ed.z)
                          return d[ed.z][ed.x][ed.y];
                     Q.push(next);
                }
            }
    }
      return -1;
}
int main()
{
   while(cin>>L>>R>>C&&(L+R+C)!=0)
   {
       sum=0;
       memset(d,0,sizeof(d));
      for(int i=0;i<L;i++)
          for(int j=0;j<R;j++)
            for(int k=0;k<C;k++)
          {
 
           cin>>a[i][j][k];
           if(a[i][j][k]=='S')
           {
               start.z=i;start.x=j;start.y=k;
           }
           else if(a[i][j][k]=='E')
           {
               ed.z=i;ed.x=j;ed.y=k;
           }
       }
      // cout<<start.x<< " "<<start.y<<" "<<start.z<<endl;
      // cout<<ed.x<<" "<<ed.y<<" "<<ed.z<<endl;
      if( bfs()==-1)
       printf("Trapped!\n");
      else
        printf("Escaped in %d minute(s).\n",d[ed.z][ed.x][ed.y]);
 
   }
    return 0;
}

POJ——3278

题意:可以对数n进行三种操作——n+1,n-1和n*2,求数n变换到k的最短路径

题解:bfs

#include<iostream>
#include<queue>
#include<string>
using namespace std;
int n, m;
const int MAX = 1e5+5;
int b[MAX];
int t[MAX];

int bfs()
{
    memset(b, 0, sizeof(b));
    memset(t, 0, sizeof(t));
    queue<int>q;
    q.push(n);
    b[n] = 1;
    int i;
    while (!q.empty()) {
        int cur, nex;
        cur = q.front();
        q.pop();
        if (cur == m)
            return t[cur];
        for (i = 0; i < 3; i++) {
            if (i == 0)
                nex = cur + 1;
            if (i == 1)
                nex = cur - 1;
            if (i == 2)
                nex = cur * 2;
            if (nex <= 1e5 && nex >= 0 && (!b[nex])) {
                t[nex] = t[cur] + 1;
                b[nex] = 1;
                q.push(nex);
            }
        }
    }
    return -1;
}

int main()
{
    cin >> n >> m;
    cout << bfs() << endl;
    return 0;
}

POJ——1383

题意:在迷宫中寻找最长相连的可走方块个数

题解:bfs

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 1005
using namespace std;
int n,m,t;
char a[maxn][maxn];
int used[maxn][maxn];//判重
const int walkx[4]={1,-1,0,0},walky[4]={0,0,1,-1};//控制走的方向
struct node{
    int x;
    int y;
    int t;
    node(){} 
    node(int xx,int yy,int tim){
        x=xx;
        y=yy;
        t=tim;
    }
};
int is_check(int x,int y){
    if(x<=0||y<=0||x>n||y>m||used[x][y]==1||a[x][y]=='#') return 0;
    else return 1;
}
node bfs(int sx,int sy){//sx,sy为起点
    memset(used,0,sizeof(used));
    queue<node>q;
    q.push(node(sx,sy,0));
    node now,nex;
    int tx,ty;
    int maxt=0,maxx=sx,maxy=sy;
    while(!q.empty()){
        now=q.front();
        q.pop();
        if(now.t>maxt){
            maxx=now.x;
            maxy=now.y;
            maxt=now.t;
        } 
        for(int i=0;i<4;i++){
            tx=now.x+walkx[i];
            ty=now.y+walky[i];
            if(is_check(tx,ty)){
                used[tx][ty]=1;
                q.push(node(tx,ty,now.t+1));
            }
        }
    }
    return node(maxx,maxy,maxt);
}
int main(){
    char tmp[maxn];
    scanf("%d",&t);
    while(t--){
        scanf("%d %d\n",&n,&m);
        swap(n,m);
        int xx,yy;
        xx=yy=-1;
        for(int i=1;i<=n;i++){
            scanf("%s",tmp+1);
            for(int j=1;j<=m;j++){
                a[i][j]=tmp[j];
                if(a[i][j]=='.'&&xx==-1&&yy==-1){
                    xx=i;
                    yy=j;
                }
            }
        }
        node tmp1=bfs(xx,yy);
        node tmp2=bfs(tmp1.x,tmp1.y);
        printf("Maximum rope length is %d.\n",tmp2.t);
    }

POJ——2243

题意:在棋盘上给定起点和终点,计算棋子“马”从起点到终点所需最短步数

题解:bfs

#include<iostream>
#include<queue>
#include<string>
using namespace std;
int book[8][8];
struct node {
    int x, y;
    int t;
};
node st, ed;
const int tr[8][2] = { {2,1},{2,-1}, {-2,1},{-2,-1}, {1,2},{1,-2}, {-1,2},{-1,-2} };
int bfs()
{
    queue<node>q;
    memset(book, 0, sizeof(book));
    book[st.x][st.y] = 1;
    q.push(st);
    while (!q.empty()) {
        node cur, nex;
        cur = q.front();
        q.pop();
        if (cur.x == ed.x && cur.y == ed.y)
            return cur.t;
        int i;
        for (i = 0; i < 8; i++) {
            nex.x = cur.x + tr[i][0];
            nex.y = cur.y + tr[i][1];
            nex.t = cur.t + 1;
            if (nex.x >= 0 && nex.x < 8 && nex.y >= 0 && nex.y < 8 && book[nex.x][nex.y] == 0) {
                book[nex.x][nex.y] = 1;
                q.push(nex);
            }
        }
    }
    return -1;
}

int main()
{
    int y1, y2;
    char x1, x2;
    while (cin>>x1>>y1>>x2>>y2) {
        st.x = x1 - 'a';
        st.y = y1 - 1;
        st.t = 0;
        ed.x = x2 - 'a';
        ed.y = y2 - 1;
        ed.t = 0;
        int ans = bfs();
        printf("To get from %c%d to %c%d takes %d knight moves.\n", x1, y1, x2, y2, ans);
    }
    return 0;
}

POJ——3279

题意:给定一个01矩阵,当一个单位翻转时,其相邻的单位数字也要翻转。求使该矩阵变为0矩阵的翻转次数最少,字典排序最小的翻转矩阵

题解:二进制枚举+bfs,设翻转矩阵为f,对f的第一行枚举所有情况,再往下得出最后一行看是否全为零

#include<iostream>
#include<queue>
#include<string>
using namespace std;
const int MAX = 20;
int map[20][20], f[20][20];
int m, n;
const int wr[4][2] = { {0,0},{-1,0},{0,-1},{0,1} };
int bw()
{
    int i, j, k;
    for (i = 1; i < m; i++) {
        for (j = 1; j <= n; j++) {
            int t = map[i][j];
            for (k = 0; k < 4; k++) {
                int tx = i + wr[k][0];
                int ty = j + wr[k][1];
                t += f[tx][ty];
            }
            if (t & 1)
                f[i + 1][j] = 1;
        }
    }
    for (j = 1; j <= n; j++) {
        int t = map[i][j];
        for (k = 0; k < 4; k++) {
            int tx = i + wr[k][0];
            int ty = j + wr[k][1];
            t += f[tx][ty];
        }
        if (t & 1)
            return -1;    
    }
    int ans = 0;
    for (i = 1; i <= m; i++) {
        for (j = 1; j <= n; j++) {
            ans += f[i][j];
        }
    }
    return ans;
}

int main()
{
    cin >> m >> n;
    int i, j, k, l;
    for (i = 1; i <= m; i++) {
        for (j = 1; j <= n; j++) 
            cin >> map[i][j];
    }
    int ans = 0x3f3f3f3f;
    int tmp[20][20];
    for (i = 0; i < (1 << n); i++) {
        memset(f, 0, sizeof(f));
        for (j = 0; j < n; j++) {
            f[1][j + 1] = (i >> j) & 1;
        }
        int t = bw();
        if (t == -1)
            continue;
        if (t < ans) {
            ans = t;
            for (k = 1; k <= m; k++) {
                for (l = 1; l <= n; l++)
                    tmp[k][l] = f[k][l];
            }
        }
    }
    if (ans == 0x3f3f3f3f)
        cout << "IMPOSSIBLE" << endl;
    else {
        for (k = 1; k <= m; k++) {
            for (l = 1; l <= n; l++)
                cout << tmp[k][l] << " ";
            cout << endl;
        }
    }
    return 0;
}

POJ——3669

题意:第一象限内有m颗陨石再不同时刻砸到不同坐标上,这些坐标相邻的坐标也会被摧毁,被摧毁后的坐标不能再经过,求从原点开始到安全地点所需走的最短步数

题解:初始化地图数组m全为-1,在通过输入修改被摧毁的坐标的m上的值为其被摧毁的最初时刻,再bfs

#include<iostream>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
int map[305][305];
const int g[5][2] = { {0,0}, {0,1},{0,-1},{1,0},{-1,0} };
struct node {
    int x, y;
    int t;
};

int bfs()
{
    if (map[0][0] == 0)  return -1;
    if (map[0][0] == -1) return 0;
    node st;
    st.x = 0; st.y = 0; st.t = 0;
    queue<node>q;
    q.push(st);
    while (!q.empty()) {
        node cur, nex;
        cur = q.front();
        q.pop();
        int i;
        for (i = 0; i < 5; i++) {
            nex.t = cur.t + 1;
            nex.x = cur.x + g[i][0];
            nex.y = cur.y + g[i][1];
            if (nex.x < 0 || nex.x>400 || nex.y < 0 || nex.y>400)
                continue;
            if (map[nex.x][nex.y] == -1)return nex.t;
            if (map[nex.x][nex.y] <= nex.t)continue;
            map[nex.x][nex.y] = nex.t;
            q.push(nex);
        }
    }
    return -1;
}

int main()
{
    int m;
    cin >> m;
    int i, x, y, t, j;
    memset(map, -1, sizeof(map));
    for (i = 0; i < m; i++) {
        cin >> x >> y >> t;
        for (j = 0; j < 5; j++) {
            int tx = x + g[j][0];
            int ty = y + g[j][1];
            if (tx < 0 || tx>400 && ty < 0 && ty>400)
                continue;
            if (map[tx][ty] == -1)    map[tx][ty] = t;
            else   map[tx][ty] = min(map[tx][ty], t);
        }
    }
    cout << bfs() << endl;
    return 0;
}

POJ——3126

题意:给两个四位素数m,n,每次只能改变某一位的数字,且改变后的数也要是素数,求从m变换到n所需最短步数

题解:素数筛(复习埃氏筛和欧式筛)+bfs

#include<iostream>
#include<queue>
#include<string>
using namespace std;
const int MAX = 1e4;
int m, n;
int prime[MAX], b[MAX];
struct node {
    int v, t;
};

void biuld()
{
    int i;
    memset(prime, 1, sizeof(prime));
    prime[1] = 0;
    for (i = 2; i * i < MAX; i++) {
        if (prime[i]) {
            for (int j = i * i; j < MAX; j+=i) {
                prime[j] = 0;
            }
        }
    }
}

int find(int x, int i, int j)
{
    if (i == 1)
        x = x / 10 * 10 + j;
    if (i == 2)
        x = x / 100 * 100 + j * 10 + x % 10;
    if (i == 3)
        x = x / 1000 * 1000 + j * 100 + x % 100;
    if (i == 4)
        x = j * 1000 + x % 1000;
    return x;
}

int bfs()
{
    queue<node>q;
    node f;
    f.v = m; f.t = 0;
    q.push(f);
    memset(b, 0, sizeof(b));
    b[m] = 1;
    while (!q.empty()) {
        node cur, nex;
        cur = q.front();
        q.pop();
        if (cur.v == n)
            return cur.t;
        int i, j;
        for (i = 1; i <= 4; i++) {
            for (j = 0; j <= 9; j++) {
                if (i == 4 && j == 0)
                    continue;
                int tmp = find(cur.v, i, j);
                if (prime[tmp] && !b[tmp]) {
                    nex.t = cur.t + 1;
                    nex.v = tmp;
                    b[tmp] = 1;
                    q.push(nex);
                }
            }
        }
    }
    return -1;
}

int main()
{
    biuld();
    int t;
    cin >> t;
    while (t--) {
        cin >> m >> n;
        int ans = bfs();
        if (ans != -1)
            cout << bfs() << endl;
        else
            cout << "Impossible" << endl;
    }
    return 0;
}

POJ——3087

题意:题目很长,意思是 先给你两个长度一样的初始状态字符串s1,s2和一个大小为两倍的最终状态的s12,按照s2的第一个先放在s12第一个再依次是s1,s2,s1…,排完后再按照长度前一半是s1新状态,后一半是s2新状态, 重复以上操作,看得到s12是否有和 最初给的最终状态的s12相同的,有输出步数,没有就输出-1.
题解:bfs+字符串处理

#include<iostream>
#include<queue>
#include<string>
#include<map>
using namespace std;
struct node {
    string s1, s2, s12;
    int t;
};

string shuffle(int c, string s1, string s2)
{
    string s12;
    int i;
    for (i = 0; i < 2 * c; i += 2) {
        s12 += s1[i / 2];
        s12 += s2[i / 2];
    }
    return s12;
}

int bfs(string s1, string s2, string s12, int c)
{
    map<string, int>m;
    queue<node>q;
    node fs;
    fs.s1 = s1; fs.s2 = s2; fs.t = 1;
    fs.s12 = shuffle(c, fs.s2, fs.s1);
    q.push(fs);
    while (!q.empty()) {
        node cur, nex;
        cur = q.front();
        q.pop();
        if (cur.s12 == s12)
            return cur.t;
        if (m[cur.s12] == 0) {
            nex.s1 = cur.s12.substr(0, c);
            nex.s2 = cur.s12.substr(c, c);
            nex.s12 = shuffle(c, nex.s2, nex.s1);
            nex.t = cur.t + 1;
            m[cur.s12] = 1;
            q.push(nex);
        }
        else
            continue;
    }
    return -1;
}

int main()
{
    int n;
    cin >> n;
    int tmp = n;
    while (n--) {
        string s1, s2, s12;
        int c;
        cin >> c >> s1 >> s2 >> s12;
        int ans = bfs(s1, s2, s12, c);
        cout << tmp - n << " " << ans << endl;
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值