7 条题解
-
0
n, m = map(int, input().split()) a = [[0] * (m + 2)] a += [[0] + list(map(int, input().split())) + [0] for _ in range(n)] a += [[0] * (m + 2)] startx, starty = map(int, input().split()) endx, endy = map(int, input().split()) dirs = [(0, -1), (-1, 0), (0, 1), (1, 0)] paths = [] def dfs(x, y, path): if (x, y) == (endx, endy): paths.append(path[:]) return a[x][y] = 0 for dx, dy in dirs: nx, ny = x + dx, y + dy if a[nx][ny] == 1: path.append((nx, ny)) dfs(nx, ny, path) path.pop() a[x][y] = 1 dfs(startx, starty, [(startx, starty)]) if paths: for path in paths: print("->".join(f"({x},{y})" for x, y in path)) else: print(-1)
-
0
非递归方式!!利用栈实现,复杂度差不多,可以说基本一样,只是减少了递归方式的空间开销。
#include<cstdio> #include<iostream> using namespace std; int posit[16][16]; //记录位置; int flag[16][16]; //记录是否走过 int end1,end2; //结束点 int dy[4]={0,-1,0,1}; //方向 int dx[4]={-1,0,1,0}; int n,m; int count=0; int mstate[300][2]; //数组模拟的栈 mstate[][0]存放y坐标,mstate[][1]存放x int top=1; //栈顶指针,指向栈顶元素的下一个位置 int whatp(int y,int x){ //当元素出站时会执行该函数,该函数为了计算回溯的方向,得出我下一次要从哪个方向开始 for(int i=0;i<4;++i){ //因为前面定义了dy,dx,顺序是左上右下,即为i=0,1,2,3 if(y==dy[i]&&x==dx[i]) return i+1; //比如我是从上面回溯过来的,那么i就是1,于是我return i+1 也就是2,告知下一次要从(i=2)右开始找 } return 4; //实际上不可能会有for循环外的情况,这里只是加上reutrn防止报错 } int main(){ cin>>n>>m; int be1,be2; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) cin>>posit[i][j]; char tmp[20]; cin>>be1>>be2>>end1>>end2; mstate[0][0]=be1; //栈底先加入第一个元素,也就是起始点 mstate[0][1]=be2; int nowx=be2,nowy=be1; //表示当前走到了哪 int newx=be2,newy=be1; //前进的坐标 int oribx=0,oriby=0; //从哪里回溯过来的坐标 int ifnext=0; //是否有坐标可以让我前进 int p=0; //从哪个方向开始 while(top>0){ //建议先从51行开始看 if(nowy==end1&&nowx==end2){ for(int k=0;k<top-1;k++){ //这里就是走到终点时要打印路径了 sprintf(tmp,"(%d,%d)->",mstate[k][0],mstate[k][1]); cout<<tmp; } count++; //找到一条路径就加一次 sprintf(tmp,"(%d,%d)",end1,end2); cout<<tmp<<endl; top--; //我还要接着寻找有没有其他路径 所以回溯 nowy=mstate[top-1][0];nowx=mstate[top-1][1]; //这里的原理和69行一样 oriby=mstate[top][0];oribx=mstate[top][1]; flag[oriby][oribx]=0; p=whatp(oriby-nowy,oribx-nowx); } else { ifnext=0; for(int i=p;i<4;++i){ //比如我p=0,那么我就从左开始 左-》上-》右-》下 如果p=2,那么我就是从右开始 右-》下 newy=nowy+dy[i];newx=nowx+dx[i]; //计算出下一个想要走的坐标 if(newy<=n&&newy>0&&newx<=m&&newx>0&&flag[newy][newx]!=1&&posit[newy][newx]!=0){//判断下一个坐标能不能走 p=0; //因为下个坐标是新的,那它一定是从 左上右下 开始走 nowy=newy;nowx=newx; //更新位置 mstate[top][0]=newy;mstate[top][1]=newx; //入栈 flag[newy][newx]=1; //标记走过 top++; ifnext=1; //这一次存在可以往下走的坐标 break; } } } if(ifnext) continue; //既然存在 可以往下走的坐标 那就不需要回溯了,跳过下面代码从头开始 top--; // 不存在可以往下走的坐标 那就要回溯了 栈顶指针向回走 nowy=mstate[top-1][0];nowx=mstate[top-1][1]; //回到上一个坐标,前面提到栈顶指针,指向栈顶元素的下一个位置 所以当前栈顶元素就top-1 oriby=mstate[top][0];oribx=mstate[top][1]; //top-1指向当前的栈顶元素,那么top指向的就是刚刚的栈顶元素 flag[oriby][oribx]=0; //把刚才回溯过来的点标记为没走过 p=whatp(oriby-nowy,oribx-nowx); //这里相当于计算出dy,dx,可以重写到函数定义处看看解释 //计算p值就是为了防止我下一次又走向刚刚回溯过来的点,陷入死循环 } if(count==0) cout<<-1; //没有路径输出-1 return 0; }
-
0
#include <iostream> #include <cstring> #include <algorithm> using namespace std; #define x first #define y second
const int N = 20; char g[N][N]; typedef pair<int, int> PII; vector<PII> res; int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; int n, m; bool st[N][N], flag; int x1, y1, x2, y2;
void dfs(int x, int y) { st[x][y] = true; if(x == x2 && y == y2) { flag = true; printf("(%d,%d)",x1,y1); for (int i = 1; i < res.size() - 1; i ++ ) printf("->(%d,%d)",res[i].x, res[i].y); printf("->(%d,%d)\n",x2,y2); } for (int i = 0; i < 4; i ++ ) { int a = x + dx[i], b = y + dy[i]; if(a<1 || a>n || b<1 || b>m || st[a][b] || g[a][b]=='0') continue; st[a][b] = true; res.push_back({a, b}); dfs(a, b); res.pop_back(); st[a][b] = false; } }
int main() { cin >> n >> m; for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= m; j ++ ) cin >> g[i][j]; cin >> x1 >> y1; cin >> x2 >> y2;
res.push_back({x1, y1}); dfs(x1, y1); if(!flag) cout << -1; return 0;
}
-
0
#include<cstdio> #include<iostream> using namespace std; int posit[16][16]; int flag[16][16]; int end1,end2; int dy[4]={0,-1,0,1}; int dx[4]={-1,0,1,0}; int n,m; int count=0; string dfs(int y,int x,string s){ char tmp[12]; if(y!=end1||x!=end2) { sprintf(tmp,"(%d,%d)->",y,x); s+=tmp; } else{ sprintf(tmp,"(%d,%d)",y,x); cout<<s<<tmp<<endl; count++; return ""; } int newy,newx; for(int i=0;i<4;++i){ newy=y+dy[i]; newx=x+dx[i]; if(newy>=1&&newy<=n&&newx>=1&&newx<=m&&posit[newy][newx]!=0&&flag[y][x]!=1){ flag[y][x]=1; dfs(newy,newx,s); flag[y][x]=0; } } return s; }; int main(){ cin>>n>>m; int be1,be2; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) cin>>posit[i][j]; cin>>be1>>be2>>end1>>end2; dfs(be1,be2,""); if(count==0) cout<<-1; return 0; }
-
0
//模板 #include <bits/stdc++.h> using namespace std; #define endl '\n' #define INF 0x3f3f3f3f3f3f3f3f
//移动向量 int dx[4] = {-1,0,1,0}; int dy[4] = {0,-1,0,1};
//创建迷宫 int a[42][42];
//起点终点 pair<int , int> Start; pair<int , int> End;
//迷宫大小 int n,m;
//方案总数 int flag = 0;
//第一次 int diyici = 1;
//该点是否来过
bool coming[42][42];//路线 vector<pair<int , int> > Path;
void dfs(pair<int , int> now) { if(now == End) { Path.push_back(End);
for(int i = 0 ; i < Path.size() - 1 ; i++) { cout << "(" << Path[i].first + 1 << "," << Path[i].second + 1 << ")" << "->"; } cout << "(" << Path[Path.size() - 1].first + 1<< "," << Path[Path.size() - 1].second + 1 << ")" << endl; flag = 1; Path.pop_back(); coming[now.first][now.second] = 0; } for(int i = 0 ; i < 4 ; i++) { Path.push_back(now); int nex = now.second + dx[i] , ney = now.first + dy[i]; if(nex >= 0 && nex < m && ney >= 0 && ney < n /*位置可取*/ && coming[ney][nex] != 1 /*下一个位置未去过*/ && a[ney][nex] == 1 /*此路可通*/) { coming[now.first][now.second] = 1; coming[ney][nex] = 1; dfs({ney,nex}); //回溯 coming[now.first][now.second] = 0; coming[ney][nex] = 0; } Path.pop_back(); } return;
}
signed main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
memset(coming , 0 , sizeof(coming) ); memset(a , 0 , sizeof(a)); //初始化迷宫 cin >> n >> m; for(int i = 0 ; i < n ; i++) { for(int j = 0 ; j < m ; j++) { cin >> a[i][j]; } } //起点和终点 int First,Second; //(y,x) //first -- y //second -- x //起点 cin >> First >> Second; Start.first = First - 1; Start.second = Second - 1; //终点 cin >> First >> Second; End.first = First - 1; // y End.second = Second - 1; // x /* r(int i = 0 ; i < n ; i++) { 1 = for(int j = 0 ; j < m ; j++) { 1 = cout << a[i][j]; } } cout << "(" << Start.first << "," << Start.second << ")" ; cout << "(" << End.first << "," << End.second << ")" ; auto temp = make_pair(1,1); if(Start == temp) { cout << endl << "Right compare" << endl; } */ dfs(Start); if(flag == 0) { cout << "-1"; } return 0;
}
-
0
DFS遍历每条路并回溯,用vector存放坐标
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> PII; vector<PII> v; const int N = 20; int mp[N][N]; int vis[N][N]; int n,m; int sx,sy; int x2,y2; int dx[] = {0,-1,0,1}; int dy[] = {-1,0,1,0}; int flag = 0; void dfs(int x,int y){ vis[x][y] = 1; if (x == x2 && y == y2) { flag = 1; printf("(%d,%d)",sx,sy); for (int i = 1; i < v.size() - 1; ++i){ printf("->(%d,%d)",v[i].first,v[i].second); } printf("->(%d,%d)\n",x2,y2); } for (int i = 0; i < 4; ++i) { int nx = x + dx[i]; int ny = y + dy[i]; if (nx < 1 || nx > n || ny < 1 || ny > m) continue; if (vis[nx][ny]) continue; if (mp[nx][ny] == 0) continue; vis[nx][ny] = 1; v.push_back({nx,ny}); dfs(nx,ny); v.pop_back(); vis[nx][ny] = 0; } return; } int main(){ scanf("%d %d",&n,&m); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { cin >> mp[i][j]; } } scanf("%d %d",&sx,&sy); scanf("%d %d",&x2,&y2); v.push_back({sx,sy}); dfs(sx,sy); if(flag == 0) printf("-1\n"); return 0; }
-
0
回溯,
注:本题需要按照😕(没错, 我就没看见这个qwq左上右下
进行移动, 不然结果会被误判?#include <cstdio> #include <vector> #include <functional> #include <utility> using namespace std; int main() { int n, m; scanf("%d %d", &n, &m); vector<vector<char>> map(n, vector<char>(m)); vector<vector<char>> ita(n, vector<char>(m)); for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) { int tmp; scanf("%d", &tmp); map[i][j] = tmp; // 1 可以走, 0 不可以走 } int s_x, s_y, e_x, e_y; scanf("%d %d", &s_y, &s_x); scanf("%d %d", &e_y, &e_x); --s_x, --s_y, --e_x, --e_y; bool tag = 1; int fx[4][2] = { {0, -1}, {-1, 0}, {0, 1}, {1, 0} }; vector<pair<int, int>> lj; // 路径 (i, j) function<void(int, int)> dfs = [&](int i, int j) { if (i < 0 || j < 0 || i >= n || j >= m) return; if (ita[i][j] || !map[i][j]) return; // 之前走过 || 不能走 if (i == e_y && j == e_x) { // 输出 for (int i = 0; i < lj.size(); ++i) { printf("(%d,%d)->", lj[i].first + 1, lj[i].second + 1); } printf("(%d,%d)\n", e_y + 1, e_x + 1); tag = 0; return; } ita[i][j] = 1; lj.push_back({i, j}); for (auto& it : fx) { dfs(i + it[0], j + it[1]); } lj.pop_back(); ita[i][j] = 0; }; dfs(s_y, s_x); if (tag) printf("-1\n"); return 0; }
- 1
信息
- ID
- 84
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 775
- 已通过
- 118
- 上传者