/****************** *布线问题.从开始位置走到结束位置.中间有封锁区域,不得进入.只能走直线或垂直线绕过 *分支界限法: *其解空间是一个图. *从起始位置s开始将其作为第一个扩展结点,与该扩展结点相邻并且可达的方格成为可行点被加入到活结点队列中,并且在图上对其标记为路径长度 *接着从活结点列表中取出队首结点作为下一个扩展结点,照上...直到搜索到f方格或者队列为空时结束. */ #include <stdio.h> #include <string.h> #include <queue> using namespace std; #define maxn 20 struct Position{ int i; int j; Position(int i = 0,int j = 0){ this->i = i; this->j = j; } //拷贝构造函数 Position(const Position& p){ this->i = p.i; this->j = p.j; } }; int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; int n; //可行区域:0,不可行区域:1.2.3.. //起点初始化为2,距离为1的点为3,距离为2的点位4... int grid[maxn][maxn]; Position s(3,2),f(4,6); int pathLen; Position path[maxn]; bool inside(Position p){ if(p.i >= 1 && p.i <= n && p.j >= 1 && p.j <= n) return true; return false; } bool findPath(){ if(s.i == f.i && s.j == f.j){ pathLen = 0; return true; } queue<Position> q; grid[s.i][s.j] = 2; Position cur,next; //第一个扩展结点(开始位置) cur = s; while(true){ for(int k = 0;k < 4;k++){ next.i = cur.i + dir[k][0]; next.j = cur.j + dir[k][1]; //约束剪枝条件:在图内且未被访问过 if(inside(next) && !grid[next.i][next.j]){ grid[next.i][next.j] = grid[cur.i][cur.j] + 1; if(next.i == f.i && next.j == f.j) goto __construct_path; q.push(next); } } //不能到达目的位置 if(q.empty()) return false; //下一个扩展结点 cur = q.front(); q.pop(); } __construct_path: pathLen = grid[f.i][f.j] - 2; cur = f; for(int k = pathLen - 1;k >= 0;k--){ path[k] = cur; //寻找前驱 for(int d = 0;d < 4;d++){ next.i = cur.i + dir[d][0]; next.j = cur.j + dir[d][1]; if(inside(next) && grid[next.i][next.j] == k + 2) break; } cur = next; } return true; } int main(){ freopen("input.txt","r",stdin); pathLen = 0; int i,j; scanf("%d",&n); for(i = 1;i <= n;i++) for(j = 1;j <= n;j++) scanf("%d",&grid[i][j]); memset(path,0,sizeof(Position)); findPath(); for(i = 1;i <= n;i++){ for(j = 1;j <= n;j++) printf("%3d",grid[i][j]); printf("/n"); } printf("%d/n",pathLen); return 0; } /*input.txt 7 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 1 0 0 0 1 0 0 1 1 1 0 0 0 0 1 1 1 0 0 0 0 */