目录
1.矩阵内部的1块
2.从1开始,+1或乘2,计算要多少次达到n
3.迷宫路径
1.矩阵内部的1块
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
using namespace std;
const int N=130,maxn=101;
int n=2,m=2,k;
int wi[N]={1,2},C[maxn][maxn]={0},inq[maxn][maxn]={0},W[maxn][maxn];
int r[]={0,0,1,-1};
int c[]={1,-1,0,0};
int step=0;int ans=-1;int w0;
struct node
{
int x,y;
}Node; // node是结构体类别名,Node是结构体的个体的名字
bool can(int x,int y)
{
if(x>n || y>m ||x<0 ||y<0) {//printf("1");
return false;}
if(inq[x][y] || !W[x][y]) {//printf("2");printf("#%d%d#$%d%d$",x,y,inq[x][y] , !W[x][y]);
return false; }
return true;
}
void bfs(int x,int y)
{
queue<node> q;
Node.x=x;Node.y=y;
q.push(Node);
inq[x][y]=1;
while(!q.empty())
{
node Node2=q.front();
q.pop();
int X=Node2.x;int Y=Node2.y;
for(int j=0;j<4;j++)
{int nx=X+r[j];int ny=Y+c[j];//printf(">");
if(can(nx,ny))
{Node.x=nx;Node.y=ny;q.push(Node);inq[nx][ny]=1;//printf("Test%d%dtesT",nx,ny);
}
}
}
}
int main()
{//D[0][0]=1;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{scanf("%d",&W[i][j]);}
int ans=0;
for(int i=0;i<n;i++)
{for(int j=0;j<m;j++)
{
if(can(i,j))
{//printf("^");
bfs(i,j);ans++;//printf("\n-%d%d-\n",i,j);
}
}
}
printf("%d",ans);
}
2.从1开始,+1或乘2,计算要多少次达到n
如何记录次数?我选择再开一个queue,
demo, 这个代码超时了
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
using namespace std;
const int N=13,maxn=10;
int n=2,m=2,k;
int wi[N]={1,2},C[maxn][maxn]={0},inq[maxn][maxn]={0},W[maxn][maxn];
int bfs(int n)
{int ans=0;
queue<int> q,q2;
q.push(1);q2.push(ans);
while(q.front()!=n)
{
int a=q.front();int a2=q2.front();//printf(" %d ",a);
q.pop();a2++;q2.pop();
q.push(a+1);q2.push(a2);
q.push(a*2);q2.push(a2);
}
return q2.front();
}
int main()
{//D[0][0]=1;
scanf("%d",&n);
//for(int i=0;i<n;i++)
//for(int j=0;j<m;j++)
//{scanf("%d",&W[i][j]);}
//int ans=0;
//for(int i=0;i<n;i++)
//{for(int j=0;j<m;j++)
//{
// if(can(i,j))
// {//printf("^");
// bfs(i,j);ans++;//printf("\n-%d%d-\n",i,j);
// }
//}
printf("%d",bfs(n));
}
改进:1.没有用一个列表记录不让他重复入队的问题 。
2.如何知道BFS深度?
我用了两个队列,或许这是超时的主要原因),答案是每次记录队列长度,遍历一个队列(同一层·时,在同一个循环里头),循环完了step++
3. //###这一步很重要 ,我之前写的是for(int i=0;i<q.size();i++),最后算出来结果不对,原因是q.size随着循环在变化,应当在循环结束时更新,而不是一边循环一边更新
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
using namespace std;
const int N=200000,maxn=10;
int n=2,m=2,k;
//int wi[N]={1,2},C[maxn][maxn]={0},inq[maxn][maxn]={0},W[maxn][maxn];
int hs[N]={0};
int bfs(int n)
{int ans=0;
queue<int> q;//,q2;
q.push(1);//q2.push(ans);
hs[1]=1;
while(1)
{
int cnt=q.size();
//###这一步很重要 ,我之前写的是for(int i=0;i<q.size();i++),最后算出来结果不对,原因是q.size随着循环在变化,应当在循环结束时更新,而不是一边循环一边更新
for(int i=0;i<cnt;i++)
{//printf("%d ",q.front());
int a=q.front();//int a2=q2.front();printf(" %d ",a);
q.pop();//a2++;q2.pop();
//if(a==n) return ans;
if(a+1==n || a*2==n) return ans+1;
//q.push(a+1);q2.push(a2);q.push(a*2);q2.push(a2);
if(!hs[a+1] && a+1<=n){q.push(a+1);hs[a+1]=1;}//&&前后最好掉一下位置,否则数组要开大一点,不然数组会越界,血与泪的教训。
if(!hs[a*2] && a*2<=n){q.push(a*2);hs[a*2]=1;}
}
ans++;
}
//return q2.front();
}
int main()
{//D[0][0]=1;
scanf("%d",&n);
//for(int i=0;i<n;i++)
//for(int j=0;j<m;j++)
//{scanf("%d",&W[i][j]);}
//int ans=0;
//for(int i=0;i<n;i++)
//{for(int j=0;j<m;j++)
//{
// if(can(i,j))
// {//printf("^");
// bfs(i,j);ans++;//printf("\n-%d%d-\n",i,j);
// }
//}
printf("%d",bfs(n));
}
思考:如何记录最佳算法?
类似于这种pre数组,用了运筹学动态规划的思想,全局最优的话,一定局部最优,
比如 如果你是从7到的14,那么,7之前一定是按照“如何到7”的最优方法走的,最后pre数组相当于打表,记录了每一个数字前一个必经之数。
具体懒得写了,将在下一个 迷宫路径 中进行具体实现。
3.迷宫路径
见下一篇