程序设计思维与实践 Week2 作业 (3/4/数据班)

A - Maze

东东有一张地图,想通过地图找到妹纸。地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹纸,这两个位置保证为0。既然已经知道了地图,那么东东找到妹纸就不难了,请你编一个程序,写出东东找到妹纸的最短路线。

Input

  输入是一个5 × 5的二维数组,仅由0、1两数字组成,表示法阵地图。

Output

  输出若干行,表示从左上角到右下角的最短路径依次经过的坐标,格式如样例所示。数据保证有唯一解。

Sample Input0 1 0 0 0
0 1 0 1 0
0 1 0 1 0
0 0 0 1 0
0 1 0 1 0
Sample Output(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)
Hint

  坐标(x, y)表示第x行第y列,行、列的编号从0开始,且以左上角为原点。

  另外注意,输出中分隔坐标的逗号后面应当有一个空格。

分析和思路

读入的是一个5*5矩阵,我建立一个7*7的,第0行、第6行、第0列、第6列赋值为1,表示四边都是墙壁。其余先赋值为0,等待读入。

采用BFS的思路,从起点(或者终点)开始,访问一个位置可以访问但没访问过的点,一旦访问,把visit数组的相应位置改写为1,之后不再访问,将这一位置的“父亲”记为上一个点,如此往复,直到访问到最后一个点。

输出时,逐行输出。

#include<iostream>
#include<queue>
using namespace std;
int maze[7][7];//迷宫,包括四面的墙壁
int visit[7][7];//记录是否访问
struct Point
{
    int x;
    int y;
    Point() :x(0), y(0) {};
    Point(int _x, int _y) :x(_x), y(_y) {};
};
Point parent[7][7];
bool bfs(Point& pb, Point& pe)
{
    queue<Point> que;
    int run[][2] = { {0,-1},{0,1},{1,0},{-1,0} };
    parent[pb.x][pb.y] = pb;
    que.push(pb);
    while (!que.empty())
    {
        Point temp = que.front();
        que.pop();
        visit[temp.x][temp.y] = 1;
        if (temp.x == pe.x && temp.y == pe.y)
            return true;
        for (int i = 0; i < 4; ++i)
        {
            Point temp2(temp.x + run[i][0], temp.y + run[i][1]);
            if (maze[temp2.x][temp2.y] == 0 && visit[temp2.x][temp2.y] == 0)
            {
                que.push(temp2);
                parent[temp2.x][temp2.y] = temp;
            }
        }
    }
    return false;
}
int main()
{
    for (int i = 0; i < 7; ++i)
        maze[0][i] = 1;
    for (int i = 0; i < 7; ++i)
        maze[i][0] = 1;
    for (int i = 0; i < 7; ++i)
        maze[6][i] = 1;
    for (int i = 0; i < 7; ++i)
        maze[i][6] = 1;
//    memset(visit, 0, sizeof(visit));
    for (int i = 1; i <= 5; ++i)
        for (int j = 1; j <= 5; ++j)
            cin >> maze[i][j];
    Point g_begin(1, 1), g_end(5, 5);
    if (bfs(g_end, g_begin))
    {
        Point a(1, 1);
        cout << "(0, 0)" << endl;
        while (a.x != 5 || a.y != 5)
        {
            a = parent[a.x][a.y];
            cout << '(' << a.x - 1 << ", " << a.y - 1 << ')' << endl;
        }
    }
    return 0;
}

B - Pour Water

倒水问题 "fill A" 表示倒满A杯,"empty A"表示倒空A杯,"pour A B" 表示把A的水倒到B杯并且把B杯倒满或A倒空。

Input

输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质。

Output

你的程序的输出将由一系列的指令组成。这些输出行将导致任何一个罐子正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。

Sample Input

2 7 5
2 7 4

Sample Output

fill B
pour B A
success 
fill A
pour A B
fill A
pour A B
success

Notes如果你的输出与Sample Output不同,那没关系。对于某个"A B C"本题的答案是多解的,不能通过标准的文本对比来判定你程序的正确与否。 所以本题由 SPJ(Special Judge)程序来判定你写的代码是否正确。

分析和思路

两个杯子,共有六种操作:A倒入B,B倒入A,A倒空,B倒空,A装满,B装满。

思路和之前的迷宫一样,区别是,迷宫每个状态下,接下来有四种选择,而倒水问题接下来有六种 选择。仍然使用类似于迷宫的解决方案,使用visit数组表示实现过的状态,这一状态如果不满足条件,就变为下一状态...

A倒入B,分为能装满和装不满两种状态,如果B瓶装不下,A剩下x+y-B,否则A倒空,剩下0,同理,可以写出其他5种状态的表达式。

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

int A, B, C;

struct Status {
    int x, y;
    Status() :x(0), y(0){}
    Status(int _x, int _y) :x(_x), y(_y){}
    bool operator<(const Status& b) const
    {
        return x == b.x ? y < b.y : x < b.x;
    }
    Status AToB()//A瓶倒入B瓶
    {
        Status c;
        c.x = max(x + y - B, 0);//如果B瓶装不下,A瓶剩x+y-B,否则A瓶空
        c.y = min(B, x + y);
        return c;
    }
    Status BToA()
    {
        Status c;
        c.y = max(x + y - A, 0);
        c.x = min(A, x + y);
        return c;
    }
    Status FillA()
    {
        return Status(A, y);
    }
    Status FillB()
    {
        return Status(x, B);
    }
    Status EmptyA()
    {
        return Status(0, y);
    }
    Status EmptyB()
    {
        return Status(x, 0);
    }
};

map<Status, bool> visit;
map<Status, string> act;
map<Status, Status> pre;
queue<Status> q;

void print(Status t) {
    if (act.find(t) != act.end())
    {
        print(pre[t]);
        cout << act[t] << endl;
    }
}
void bfs(int a, int b)
{
    visit.clear();
    act.clear();
    pre.clear();

    Status t(a, b);
    q.push(t);
    visit[t] = 1;
    while (!q.empty())
    {
        t = q.front();
        q.pop();
        if (t.x == C || t.y == C)
        {
            print(t);
            return;
        }
        Status x = t.AToB();
        if (visit[x] == 0)
        {
            visit[x] = 1;
            q.push(x);
            act[x] = "pour A B";
            pre[x] = t;
        }
        x = t.BToA();
        if (visit[x] == 0)
        {
            visit[x] = 1;
            q.push(x);
            act[x] = "pour B A";
            pre[x] = t;
        }
        x = t.FillA();
        if (visit[x] == 0)
        {
            visit[x] = 1;
            q.push(x);
            act[x] = "fill A";
            pre[x] = t;
        }
        x = t.FillB();
        if (visit[x] == 0)
        {
            visit[x] = 1;
            q.push(x);
            act[x] = "fill B";
            pre[x] = t;
        }
        x = t.EmptyA();
        if (visit[x] == 0)
        {
            visit[x] = 1;
            q.push(x);
            act[x] = "empty A";
            pre[x] = t;
        }
        x = t.EmptyB();
        if (visit[x] == 0)
        {
            visit[x] = 1;
            q.push(x);
            act[x] = "empty B";
            pre[x] = t;
        }
    }
}

int main() {
    while (cin >> A >> B >> C)
    {
        while (!q.empty())
            q.pop();
        bfs(0, 0);
        cout << "success" << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/master-cn/p/12411883.html