A题目:
东东有一张地图,想通过地图找到妹纸。地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹纸,这两个位置保证为0。既然已经知道了地图,那么东东找到妹纸就不难了,请你编一个程序,写出东东找到妹纸的最短路线。
输入:输入是一个5 × 5的二维数组,仅由0、1两数字组成,表示法阵地图。
输出:输出若干行,表示从左上角到右下角的最短路径依次经过的坐标,格式如样例所示。数据保证有唯一解。
样例输入:
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
样例输出:
(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开始,且以左上角为原点。
另外注意,输出中分隔坐标的逗号后面应当有一个空格。
整体思路:
迷宫类题目具有一定的固定解法,利用队列先进先出的特性,我们可以利用bfs的思想对距离进行广搜,而逐步获取距离连续的点,这样相当于在寻找路径的时候为每个点做了标记,使得我们再一步获取路径时更方便。本道题目有着特殊的限制:即保证了线路只有一条,这使得我们回来找路径时处理更简单,考虑的更少。例如在代码段func2中,我们利用递归寻找路径,因为输出是从(0,0)点开始的,如果我们从原点考虑以末尾点为结束标志的话,我们func2中的break语句必须要加,因为从头开始循环找路径时路径会分叉,但是由于题目保证路径只有一条,所以我们可以考虑从末尾点开始考虑,以初始点作为递归弹出点,这样可以保证路径不会分叉。当然,我们同样也可以考虑利用break语句避免分叉输出,而且又能够节省时间消耗。
#include<iostream>
#include<queue>
using namespace std;
int fun[5][5];
int x[4]={1,-1,0,0};
int y[4]={0,0,1,-1};
void func(int fun[][5])
{
queue<pair<int,int> > mp;
pair<int,int> p(0,0);
mp.push(p);//(0,0)点入队列;
while(!mp.empty())
{
pair<int,int>a=mp.front();
mp.pop();
for(int i=0;i<4;i++)//对上下左右四个点分别进行考虑;
{
int newx=a.first+x[i];
int newy=a.second+y[i];
if(0<=newx&&newx<=4&&0<=newy&&newy<=4)//防止越过边界;
{
if(fun[newx][newy]==0)
{
fun[newx][newy]=fun[a.first][a.second]+1;
mp.push(pair<int,int>(newx,newy));
if(fun[4][4]!=0)//循环终止条件;
return;
}
}
}
}
}
void func2(int fun[][5],int a,int b)
{
if(a==0&&b==0)
{
cout<<"("<<0<<","<<" "<<0<<")"<<endl;
return;
}
for(int i=0;i<4;i++)
{
if(0<=a-x[i]&&a-x[i]<=4&&0<=b-y[i]&&b-y[i]<=4)
{
if(fun[a-x[i]][b-y[i]]==fun[a][b]-1)
{
func2(fun,a-x[i],b-y[i]);//利用递归,从终点回溯的起点;
cout<<"("<<a<<","<<" "<<b<<")"<<endl;
//break;//此题不写也可以,但写了可以降低时间消耗;
}
}
}
}
int main()
{
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
cin>>fun[i][j];
}
}
fun[0][0]=2;//为了不与输入的0,1搞混,我们取值为2;
func(fun);
func2(fun,4,4);
}
B题目:
倒水问题
“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题的思路有着一定的相似之处,A杯与B杯的状态属于一个点,于是我们借助A题的思想,其每一个点的扩展方向有大方向分四种,小方向分六中,将A倒空,将B倒空,将A倒入B中,将B倒入A中。因为我们最终是要到达A杯中或B杯中水为定容量,故一种状态到达一次即可,此时,我们可以利用map的映射特性,将到达过的状态加入map,这里对于Map的第一维和第二维的问题存在一个选择问题,在这里,我们将end作为第一维,将from作为第二维,这其中from与end状态的关系相似一棵树,应当将出度的点作为第一维。同样利用队列的特性以及bfs的思想进行搜索。不过,由于这种映射关系,我们只能够从末位状态进行考虑追溯的原始状态,这样,我们将每一步的操作存入到一个vector中,最终我们再倒序输出vector中的元素即可。
#include<iostream>
#include<map>
#include<string>
#include<queue>
#include<vector>
using namespace std;
struct status {
int x, y;
status(){
}
status(int a, int b) {
x = a;
y = b;
}
bool operator<(const status& p)const {
return x == p.x ? y < p.y : x < p.x;
}
};
map<status, status> mp;//第一维表示end,第二维表示from;
void func(int a, int b, int c) {
queue<status> ls;
status from(0, 0); ls.push(from);
while (!ls.empty()) {
from = ls.front();
ls.pop();
//将a杯倒空;
if (mp.find(status(0, from.y)) == mp.end()) {
ls.push(status(0, from.y));
mp[status(0, from.y)] = status(from.x, from.y);
}
//将b杯倒空:
if (mp.find(status(from.x, 0)) == mp.end()) {
ls.push(status(from.x, 0));
mp[status(from.x, 0)] = status(from.x, from.y);
}
//将a杯倒满;
if (mp.find(status(a, from.y)) == mp.end()) {
ls.push(status(a, from.y));
mp[status(a, from.y)] = status(from.x, from.y);
}
//将b杯倒满;
if (mp.find(status(from.x, b)) == mp.end()) {
ls.push(status(from.x, b));
mp[status(from.x, b)] = status(from.x, from.y);
}
//将a中的水倒入b杯中;
if (from.x+from.y > b) {
if (mp.find(status(from.x + from.y - b, b)) == mp.end()) {
ls.push(status(from.x + from.y - b, b));
mp[status(from.x + from.y - b, b)] = status(from.x, from.y);
}
} else {
if (mp.find(status(0, from.x + from.y)) == mp.end()) {
ls.push(status(0, from.x + from.y));
mp[status(0, from.x + from.y)] = status(from.x, from.y);
}
}
//将b中的水倒入a中;
if (from.x+from.y > a) {
if (mp.find(status(a, from.x + from.y - a)) == mp.end()) {
ls.push(status(a, from.x + from.y - a));
mp[status(a, from.x + from.y - a)] = status(from.x, from.y);
}
} else {
if (mp.find(status(from.x + from.y, 0)) == mp.end()) {
ls.push(status(from.x + from.y, 0));
mp[status(from.x + from.y, 0)] = status(from.x, from.y);
}
}
if (mp.find(status(0, c)) != mp.end() || mp.find(status(c, 0)) != mp.end())
break;
}
}
void print(int a1, int b1, int c1) {
vector<string> pri;
string str;
if (mp.find(status(0, c1)) != mp.end()) {
int endx = 0, endy = c1;
int a = -1, b = -1;
while (!(a == 0 && b == 0)) {
status from = mp[status(endx, endy)];
a = from.x;
b = from.y;
if (endx == a && endy == 0) {
str = "empty B";
pri.push_back(str);
endx=a;
endy=b;
} else if (endx == a && endy == b1) {
str = "fill B";
pri.push_back(str);
endx=a;
endy=b;
} else if (endx + endy == a + b) {
if (endx == 0 || endy == b1) {
str = "pour A B";
pri.push_back(str);
endx=a;
endy=b;
}
if (endy == 0 || endx == a1) {
str = "pour B A";
pri.push_back(str);
endx=a;
endy=b;
}
} else if (endx == 0 && endy == b) {
str = "empty A";
pri.push_back(str);
endx=a;
endy=b;
} else if (endx == a1 && endy == b) {
str = "fill A";
pri.push_back(str);
endx=a;
endy=b;
}
}
int size = pri.size();
for (int i = size - 1; i >= 0; i--) {
cout << pri[i] << endl;
}
cout << "success"<<endl;
return;
} else if (mp.find(status(c1, 0)) != mp.end()) {
int endx = c1, endy = 0;
int a = -1, b = -1;
while (!(a == 0 && b == 0)) {
status from = mp[status(endx, endy)];
a = from.x;
b = from.y;
if (endx == a && endy == 0) {
str = "empty B";
pri.push_back(str);
endx=a;
endy=b;
} else if (endx == a && endy == b1) {
str = "fill B";
pri.push_back(str);
endx=a;
endy=b;
} else if (endx + endy == a + b) {
if (endx == 0 || endy == b1) {
str = "pour A B";
pri.push_back(str);
endx=a;
endy=b;
}
if (endy == 0 || endx == a1) {
str = "pour B A";
pri.push_back(str);
endx=a;
endy=b;
}
} else if (endx == 0 && endy == b) {
str = "empty A";
pri.push_back(str);
endx=a;
endy=b;
} else if (endx == a1 && endy == b) {
str = "fill A";
pri.push_back(str);
endx=a;
endy=b;
}
}
}
int size = pri.size();
for (int i = size - 1; i >= 0; i--) {
cout << pri[i] << endl;
}
cout << "success"<<endl;
}
int main() {
int a, b, c;
while(cin >> a >> b >> c)
{
mp.clear();
func(a, b, c);
print(a, b, c);
}
}在这里插入代码片