Programación pensamiento semana 2 tarea

Programación tarea de pensamiento semana2

本次作业的两个题都是BFS的典型应用。

Problema A: laberinto

1. Resumen del tema

Dongdong tiene un mapa y quiere encontrar el papel hermano a través del mapa. El mapa muestra que 0 significa que puedes caminar, 1 significa que no puedes caminar, la esquina superior izquierda es la entrada y la esquina inferior derecha es el papel hermano. Estas dos posiciones están garantizadas como 0. Ahora que conoce el mapa, no es difícil para Dongdong encontrar papel hermano. Por favor, escriba un programa para escribir la ruta más corta para que Dongdong encuentre papel hermano.

2 entrada

La entrada es una matriz bidimensional de 5 × 5, que consta de solo dos dígitos 0 y 1, que representa un mapa de matriz normal.

3.Salida

Se generan varias líneas, que representan las coordenadas de la ruta más corta desde la esquina superior izquierda a la esquina inferior derecha, en el formato que se muestra en la muestra. Se garantiza que los datos tendrán una solución única.

4. Muestra

entrada de muestra

0 1 0 0 0
0 1 0 1 0
0 1 0 1 0
0 0 0 1 0
0 1 0 1 0

salida de muestra

(0, 0)
(1, 0)
(2, 0)
(3, 0)
(3, 1)
(3, 2)
(2, 2)
(1, 2)
(0, 2)
(0, 3)
(0, 4)
(1, 4)
(2, 4)
(3, 4)
(4, 4)

5. La idea general

La idea es relativamente simple: use la pila para simular el proceso BFS, guarde el que llegue con éxito al punto final en la pila y luego use la otra pila para generar el resultado en orden inverso.

6. Código

#include<iostream>
#include<stack>
using namespace std;
//记录点的坐标
class point
{
public:
    point(int x,int y)
    {
        _x=x;
        _y=y;
    }
    void output()
    {
        cout<<'('<<_x-1<<','<<' '<<_y-1<<')'<<endl;
    }
public:
    int _x;
    int _y;

};

int _dx[]={1,0,0,-1};
int _dy[]={0,-1,1,0};
stack<point> track;
int a[7][7];
int main()
{
    //初始化
    for(int i=0;i<7;i++)
    {
        for(int j=0;j<7;j++)
        {
            if((i*j==0)||i==6||j==6)
                a[i][j]=1;
            else cin>>a[i][j];
        }
    }
    //输入起点
    point start(1,1);
    point terminate(5,5);
    track.push(start);
    //判断终点条件
    while(!(track.top()._x==5&&track.top()._y==5))
    {
        point now=track.top();
        a[now._x][now._y]=1;
        int i;
        //BFS过程
        for(i=0;i<4;i++)
        {
            int new_x=now._x+_dx[i];
            int new_y=now._y+_dy[i];
            if(a[new_x][new_y]!=1)
            {
                a[new_x][new_y]=1;
                track.push({new_x, new_y});
                break;
            }
        }
        if(i==4) track.pop();
    }
    int size=track.size();
    stack<point> newtrack;
    for(int k=0;k<size;k++)
    {
        point n(track.top()._x,track.top()._y);
        track.pop();
        newtrack.push(n);
    }
    for(int i=0;i<size;i++)
    {
        newtrack.top().output();
        newtrack.pop();
    }
    return 0;
}

Problema B: vierta agua

1. Resumen del tema

Problema de verter agua "llenar A" significa llenar la taza A, "vaciar A" significa vaciar la taza A, "verter AB" significa verter el agua de A en la taza B y vaciar la taza B o A.

2. Muestra de entrada y salida

Entrada

La entrada contiene múltiples conjuntos de datos. Cada grupo de entrada de datos A, B, C rango de datos 0 <A <= B, C <= B <= 1000, A y B son relativamente primos.

Entrada de muestra
2 7 5
2 7 4

Salida

La salida de su programa consistirá en una serie de instrucciones. Estas líneas de salida harán que cualquier tanque contenga exactamente C unidades de agua. La salida de la última línea de cada conjunto de datos debe ser "exitosa". La línea de salida comienza en la columna 1, y no debe haber líneas en blanco ni espacios finales.

Salida de muestra
fill B
pour B A
success 
fill A
pour A B
fill A
pour A B
success

3. La idea general y el código

Esta pregunta también es la aplicación de BFS. Reemplace la expansión de movimiento arriba-abajo, izquierda-derecha en el problema A por completo, vacío y A (B) a B (A). Mediante el uso del mapa puede registrar el estado del estado anterior de un estado. Luego, de acuerdo con la diferencia entre los dos estados para determinar la operación específica en este paso.

#include<iostream>
#include<queue>
#include<map>
using namespace std;

struct Status
{
    int a, b;
    bool operator<(const Status &s) const
    {
        return a!=s.a ? a<s.a : b<s.b;
    }
};

/* 递归输出方案 */
void print(Status &p,map<Status, Status> from)
{
    if ( from.find(p) == from.end())
    {
        //cout<<"success"<<endl;
        return ;
    }
    if(p.a == 0&&p.b==0)
    {
        return ;
    }
    print(from[p],from); // 递归
    int _a=from[p].a;
    int _b=from[p].b;
    if(p.a!=_a)
    {
        if(p.a>_a)
        {
            if(p.b<_b)
                cout<<"pour B A"<<endl;
            else
                cout<<"fill A"<<endl;
        } else{
            if(p.b>_b)
                cout<<"pour A B"<<endl;
            else
                cout<<"empty A"<<endl;
        }
    } else{
        //p.a==_a
        if(p.b>_b)
            cout<<"fill B"<<endl;
        else
            cout<<"empty B"<<endl;
    }
    //printf("-><%d,%d>",  p.a, p.b);
}

void refresh(Status &s, Status &t,map<Status, Status> &from,queue<Status> &Q)
{
    if ( from.find(t) == from.end() )
    { // 特判合法,加入队列
        from[t] = s;
        Q.push(t);
    }
}

void bfs(int A, int B, int C,map<Status, Status> from,queue<Status> &Q)
{
    // 起点, 两杯水都空
    Status s,t;
    s.a=0; s.b=0;
    Q.push(s);

    while (!Q.empty())
    {
        // 取队首
        s = Q.front();
        Q.pop();
        // 特判到达终点
        if (s.a == C || s.b == C) {
            print(s,from); // 输出方案
            return;
        }

        // 倒空 a 杯的水
        if (s.a > 0) {
            t.a = 0;  // 倒空
            t.b = s.b;// b 杯不变
            refresh(s, t,from,Q);
        }

        // 同理,倒空 b 杯的水
        if (s.b > 0) {
            t.b = 0;  // 倒空
            t.a = s.a;// a 杯不变
            refresh(s, t,from,Q);
        }

        // a 杯未满,续满 a 杯
        if (s.a < A)
        {
            // 续满 a 杯
            t.a = A;
            t.b = s.b;
            refresh(s, t,from,Q);

            // 考虑倒入
            if (s.b != 0)
            {
                if (s.a + s.b <= A)
                {
                    t.a = s.a + s.b;
                    t.b = 0;
                    refresh(s, t,from,Q);
                } else
                {
                    t.a = A;
                    t.b = s.a + s.b - A;
                    refresh(s, t,from,Q);
                }
            }
        }

        // 同理,b 杯未满,续满 b 杯
        if (s.b < B)
        {
            t.a = s.a;
            t.b = B;
            refresh(s, t,from,Q);
            if (s.a != 0)
            {
                if (s.a + s.b <= B)
                {
                    t.a = 0;
                    t.b = s.a + s.b;
                    refresh(s, t,from,Q);
                } else
                {
                    t.a = s.a + s.b - B;
                    t.b = B;
                    refresh(s, t,from,Q);
                }
            }
        }
    }
    printf("-1\n");
}
int main()
{
    int a;
    while (cin>>a) {
        queue<Status> Q;
        map<Status, Status> from;
        int b,c;
        cin>>b;
        cin>>c;
        bfs(a, b, c,from,Q);
        cout<<"success"<<endl;
    }
    return 0;
}
8 artículos originales publicados · Me gusta2 · Visitas 252

Supongo que te gusta

Origin blog.csdn.net/lawrenceY/article/details/104688670
Recomendado
Clasificación