标签:条件 bsp queue images set strong boa 遍历 运算符
定义一个二维数组:
int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, };
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0
(0, 0) (1, 0) (2, 0) (2, 1) (2, 2) (2, 3) (2, 4) (3, 4) (4, 4)
1 #include<iostream> 2 #include<queue> 3 #include<cstring> 4 #include<stack> 5 using namespace std; 6 int maze[7][7]; //必须是7,不然会溢出 7 struct node{ 8 int x, y, step; 9 }; 10 queue<node>q; 11 bool visited[6][6]; 12 int dirx[4] = {1,0,-1,0}; 13 int diry[4] = {0,1,0,-1}; 14 node way[6][6]; //记录每个点的父节点 15 stack<node>w; //存路径 16 17 int main(){ 18 int i, j; 19 memset(maze,-1,sizeof(maze)); //可以走的路是0 20 for(i = 1; i <= 5; i++) 21 for(j = 1; j <= 5; j++){ 22 cin>>maze[i][j]; 23 } 24 node p; p.x = 1; p.y = 1; p.step = 0; 25 q.push(p); 26 visited[1][1] = true; 27 while(!q.empty()){ 28 p = q.front(); 29 q.pop(); 30 if(p.x == 5 && p.y == 5){//找到终点 31 while(1){ 32 w.push(p); 33 if(p.x == 1 && p.y == 1) break; 34 p = way[p.x][p.y]; 35 } 36 //输出 37 while(!w.empty()){ 38 p = w.top(); 39 cout<<"("<<p.x-1<<", "<<p.y-1<<")"<<endl; 40 w.pop(); 41 } 42 } 43 for(i = 0; i < 4; i++){ 44 int nx = p.x+dirx[i]; 45 int ny = p.y+diry[i]; 46 if(maze[nx][ny] == 0 && !visited[nx][ny]){ 47 node no; 48 no.x = nx; no.y = ny; 49 no.step = p.step+1; 50 q.push(no); 51 visited[nx][ny] = true; 52 way[nx][ny] = p; 53 } 54 } 55 } 56 return 0; 57 }
备注:这道题在博客里写过。。不知道咋用深搜做,所以就跟上次一样用广搜写的。唯一注意的一点是,可以把数组开大一点,然后memset为-1,然后从(1,1)开始输入,这样的好处是不用判断数组下标是否出界,四周都留了余量。
2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1
2 1
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 int n, k; 5 char board[9][9]; 6 bool visited[9]; //第i列有没有棋子 7 int ans = 0; 8 void dfs(int step, int left){ 9 if(left==0){ 10 ans++; 11 return; 12 } 13 if(step == n ) return; 14 //if(step+left>n) return; 15 for(int i = 1; i <= n; i++){ 16 if(board[step+1][i]==‘#‘&&!visited[i]){ 17 visited[i] = true; 18 dfs(step+1, left-1); 19 visited[i] = false; 20 } 21 } 22 dfs(step+1,left); //第step+1行不放棋子 23 } 24 25 int main(){ 26 while(1){ 27 cin>>n>>k; 28 if(n == -1) return 0; 29 int i, j; 30 memset(board,0,sizeof(board)); 31 memset(visited,0,sizeof(visited)); 32 ans = 0; 33 for(i = 1; i <= n; i++) 34 for(j = 1; j <= n; j++) 35 cin>>board[i][j]; 36 dfs(0, k); 37 cout<<ans<<endl; 38 } 39 return 0; 40 }
备注:这道题数据好像特别水,也不用剪枝就能过。别忘了考虑某一行可以放棋子也可以不放棋子。
“我是要成为海贼王的男人!”,路飞一边喊着这样的口号,一边和他的伙伴们一起踏上了伟大航路的艰险历程。
路飞他们伟大航路行程的起点是罗格镇,终点是拉夫德鲁(那里藏匿着“唯一的大秘宝”——ONE PIECE)。而航程中间,则是各式各样的岛屿。
因为伟大航路上的气候十分异常,所以来往任意两个岛屿之间的时间差别很大,从A岛到B岛可能需要1天,而从B岛到A岛则可能需要1年。当然,任意两个岛之间的航行时间虽然差别很大,但都是已知的。
现在假设路飞一行从罗格镇(起点)出发,遍历伟大航路中间所有的岛屿(但是已经经过的岛屿不能再次经过),最后到达拉夫德鲁(终点)。假设他们在岛上不作任何的停留,请问,他们最少需要花费多少时间才能到达终点?
样例输入1: 4 0 10 20 999 5 0 90 30 99 50 0 10 999 1 2 0 样例输入2: 5 0 18 13 98 8 89 0 45 78 43 22 38 0 96 12 68 19 29 0 52 95 83 21 24 0
样例输出1: 100 样例输出2: 137
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 int n; 5 int island[17][17]; 6 bool visited[17]; 7 const int maxx = 1<<30; 8 int ans = maxx; 9 int totalen = 0; //正在走的路的长度 10 int state = 0; 11 int midl[1<<15][16];//经过状态state到达k所用的时间 12 void dfs(int cur, int step){ //当前岛屿,步数 13 if(step == n-1){ //到倒数第二个岛 14 ans = min(ans, totalen+island[cur][n]); 15 return; 16 } 17 for(int i = 2; i <= n-1; i++){ 18 if(visited[i]==true) continue; 19 if(totalen+island[cur][i]>=ans) continue; 20 if(totalen+island[cur][i]>=midl[state|(1<<(i - 2))][i]) continue; //i-2是因为从2开始所以节约一点位数 21 visited[i] = true; 22 totalen += island[cur][i]; 23 state|=(1<<(i - 2)); 24 midl[state][i] = totalen; //这会儿肯定是最小的 25 dfs(i, step+1); 26 visited[i] = false; 27 state^=(1<<(i - 2)); 28 totalen -= island[cur][i]; 29 } 30 } 31 32 int main(){ 33 int i, j; 34 cin>>n; 35 for(i = 1; i <= n; i++) 36 for(j = 1; j <= n; j++) 37 cin>>island[i][j]; 38 for(i = 1; i < 1<<(n-1); i++) 39 for(j = 1; j <= n-1; j++) 40 midl[i][j] = maxx; 41 dfs(1, 1); 42 cout<<ans; 43 return 0; 44 }
备注:这道题就是必须用状压+剪枝才能过!也就是用Midl这个数组来记录中间状态,midl[state][k]表示在state状态下,当前位置是k的最短时间。state就是要用状态压缩,用一个整型来表示此时1-n这些地点里已经经过了哪些(包括k这个点)。最多有16个岛,掐头去尾用一个14位二进制数就可以表示,所以数组要开1<<15,因为14个岛全部经过也就是1<<15-1; 注意,左右移运算符的优先级很高,所以后面是表达式记得要加括号。state用一个全局变量来存就行,就跟visited一样是参与回溯过程的。
这个dfs可以当模板记下来。边界条件不需要走到终点,走了n-1就可以,因为最后一步肯定要走到n。剪枝的过程放在寻找下一个点的时候来进行。
注意midl的初始化!!因为i和j的范围我错了好几次。
标签:条件 bsp queue images set strong boa 遍历 运算符
原文地址:https://www.cnblogs.com/fangziyuan/p/13073080.html