CRP week6 周报

本周学bfs广度优先搜索,当题目求最短路径,最小步数等最优解问题时,优先使用bfs,因为一找到答案就可以停止搜索了;

P1135 奇怪的电梯

1.思路:非常普通的一道训练dfs的模板题。

2.代码:

#include <bits/stdc++.h>
using namespace std;
int vis[205];
int ss[2]={1,-1};
int ans[205];
int k[205];
queue<int> q;
int main()
{
	int n,a,b;
	cin>>n>>a>>b;
	memset(vis,-1,sizeof(vis));
	for(int i=1;i<=n;i=i+1)
	{
		cin>>k[i];
	}
	vis[a]=0;
	q.push(a);
	while(!q.empty())
	{
		int zx=q.front();
		q.pop();
		for(int i=0;i<2;i=i+1)
		{
			int nx=zx+ss[i]*k[zx];
			if(nx<=n&&nx>=1&&vis[nx]==-1)
			{
				vis[nx]=vis[zx]+1;
				if(nx==b)
				{
					break;
				}
				q.push(nx);
			}
		}
	}
	cout<<vis[b];
}

P1443 马的遍历

1.思路:也是一道非常easy的模板题,但因为我们需要同时储存x,y这两个坐标点,所以创建队列时queue <pair<int,int> >p,用q.push(make_pair(x,y))来将点的信息存入队列中

2.代码:

P3958 [NOIP2017 提高组] 奶酪

1.思路:感觉思路很简单,但不管怎么改都只有80分,很崩溃,先放个80分代码。(三天后:这题是真恶心啊,好吧是我太废物了,两个相乘会爆掉,需要将其转为long long)

2.代码:

#include <bits/stdc++.h>
using namespace std;
long long x[1005],y[1005],z[1005];
int vis[1005];
int d[1005][1005];
long long dist(int x1,int y1,int z1,int x2,int y2,int z2)
{
	return (long long)(x1-x2)*(x1-x2)+(long long)(y1-y2)*(y1-y2)+(long long)(z1-z2)*(z1-z2);
}
queue<int>q;
int main()
{
	int t;
	cin>>t;
	for(int k=1;k<=t;k=k+1)
	{
		while(!q.empty())
		{
			q.pop();
		}
		memset(vis,0,sizeof(vis));
		memset(d,0,sizeof(d));
		int ff=0;
		long long n,h,r;
		cin>>n>>h>>r;
		for(int i=1;i<=n;i=i+1)
		{
			cin>>x[i]>>y[i]>>z[i];
			if(abs(z[i])<=r)
			{
				vis[i]=1;
				q.push(i);
			}
		}
		for(int i=1;i<=n;i=i+1)
		{
			for(int j=i+1;j<=n;j=j+1)
			{
				if(dist(x[i],y[i],z[i],x[j],y[j],z[j])<=2*2*r*r)
				{
					d[i][j]=1;
					d[j][i]=1;
				}
			}
		}
		while(!q.empty())
		{
			int zx=q.front();
			if(abs(h-z[zx])<=r)
			{
				ff=1;
				cout<<"Yes"<<endl;
				break;
			}
			q.pop();
			for(int i=1;i<=n;i=i+1)
			{
				if(d[zx][i]==1&&vis[i]==0)
				{
					vis[i]=1;
					q.push(i);
				}
			}
		}
		if(ff==0)
		{
			cout<<"No"<<endl;
		}
	}
}

P1162 填涂颜色

1.思路:这道题是搜索里找连通块的题目,用深搜找而且不用回溯

2.代码:

P3956 [NOIP2017 普及组] 棋盘

1.思路:这道题很容易就超时了,所以我们需要进行适当的剪枝,才能够通过题目。我们可以开个d数组记录到达i,j的最小花费,每次搜索前判断花费是否小于d,否则不搜(记忆化剪枝);还可以开个vis数组来记录i,j是否走过,如果走过就不搜(最普通的剪枝)

2.代码:

#include <bits/stdc++.h>
using namespace std;
int a[105][105];
int sx[4]={-1,0,1,0};
int sy[4]={0,1,0,-1};
int vis[105][105];
int d[105][105];
int ans=0x3f3f3f3f;
int hf;
int n,m;
int f=-1;
void dfs(int x,int y,int z)
{
	if(x==m&&y==m)
	{
		if(hf<ans)
		{
			f=1;
			ans=hf;
		}
		return;
	}
	else
	{
		for(int i=0;i<4;i=i+1)
		{
			int nx=x+sx[i];
			int ny=y+sy[i];
			if(vis[nx][ny]==0&&nx>=1&&nx<=m&&ny>=1&&ny<=m)
			{
				if(a[nx][ny]!=-1)
				{
					if(a[nx][ny]==a[x][y])
					{
						vis[nx][ny]=1;
						d[nx][ny]=hf;
						dfs(nx,ny,0);
						vis[nx][ny]=0;
					}
					else 
					{
						if(hf+1<d[nx][ny])
						{
							hf=hf+1;
							d[nx][ny]=hf;
							vis[nx][ny]=1;
							dfs(nx,ny,0);
							vis[nx][ny]=0;
							hf=hf-1;
						}
					}
				}
				else
				{
					if(z==0)
					{
						if(hf+2<d[nx][ny])
						{
							hf=hf+2;
							a[nx][ny]=a[x][y];
							vis[nx][ny]=1;
							d[nx][ny]=hf;
							dfs(nx,ny,1);
							hf=hf-2;
							vis[nx][ny]=0;
							a[nx][ny]=-1;
						}
					}
				}
			}
		}
	}
}
int main()
{
	memset(a,-1,sizeof(a));
	memset(d,0x3f3f3f3f,sizeof(d));
	cin>>m>>n;
	for(int i=1;i<=n;i=i+1)
	{
		int x,y,c;
		cin>>x>>y>>c;
		a[x][y]=c;
	}
	vis[1][1]=1;
	dfs(1,1,0);
	if(f==-1)
	{
		cout<<f<<endl;
	}
	else
	{
		cout<<ans<<endl;
	}
}

P1126 机器人搬重物

1.思路:这道题用广搜是最合适的,因为咱们找到最小的答案就可以退出了,而dfs我们很可能会因为搜索次数过多而被时间限制(剪枝了也很可能没用)。另外,坐标点在网格线上移动,所以我们需要对输入进行优化,而且状态的分类也很复杂,一共有4乘以3=12种状态。

2.代码:

#include <bits/stdc++.h>
using namespace std;
int a[55][55];
int vis[55][55][5];
int xyb[3]={1,2,3};
int fx[4]={1,2,3,4};
int qx,qy,zx,zy;
int ans=0x3f3f3f3f;
int sj=0;
int d[55][55][5];
int n,m;
int fff=-1;
void dfs(int x,int y,int z)
{
	if(x==zx&&y==zy)
	{
		fff=1;
		ans=min(ans,sj);
	}
	else
	{
		for(int i=0;i<4;i=i+1)
		{
			int nz=fx[i];
			int nx,ny;
			if(nz==1)
			{
				for(int j=0;j<3;j=j+1)
				{
					int nx=x;
					int ny=y+xyb[j];
					if(nx>=1&&nx<=n-1&&ny>=1&&ny<=m-1&&vis[nx][ny][nz]==0)
					{
						int f=1;
						for(int k=xyb[j]-1;k>=0;k=k-1)
						{
							if(a[nx][ny-k]==1)
							{
								f=0;
								break;
							}
						}
						
						if(f==0)
						{
							break;
						}
						if(f==1)
						{
							int ff=0;
							if(abs(z-nz)==2)
							{
								ff=1;
							}
							else if(z==nz)
							{
								ff=2;
							}
							if(ff==1&&sj+3<d[nx][ny][nz])
							{		
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+3;
								sj=sj+3;
								dfs(nx,ny,nz);
								sj=sj-3;
								vis[nx][ny][nz]=0;
							}
							else if(ff==0&&sj+2<d[nx][ny][nz])
							{
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+2;
								sj=sj+2;
								dfs(nx,ny,nz);
								sj=sj-2;
								vis[nx][ny][nz]=0;
							}
							else if(ff==2&&sj+1<d[nx][ny][nz])
							{
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+1;
								sj=sj+1;
								dfs(nx,ny,nz);
								sj=sj-1;
								vis[nx][ny][nz]=0;
							}
						}
					}
				}
			}
			if(nz==2)
			{
				for(int j=0;j<3;j=j+1)
				{
					int nx=x+xyb[j];
					int ny=y;
					if(nx>=1&&nx<=n-1&&ny>=1&&ny<=m-1&&vis[nx][ny][nz]==0)
					{
						int f=1;
						for(int k=xyb[j]-1;k>=0;k=k-1)
						{
							if(a[nx-k][ny]==1)
							{
								f=0;
								break;
							}
						}
						if(f==0)
						{
							break;
						}
						if(f==1)
						{
							int ff=0;
							if(abs(z-nz)==2)
							{
								ff=1;
							}
							else if(z==nz)
							{
								ff=2;
							}
							if(ff==1&&sj+3<d[nx][ny][nz])
							{		
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+3;
								sj=sj+3;
								dfs(nx,ny,nz);
								sj=sj-3;
								vis[nx][ny][nz]=0;
							}
							else if(ff==0&&sj+2<d[nx][ny][nz])
							{
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+2;
								sj=sj+2;
								dfs(nx,ny,nz);
								sj=sj-2;
								vis[nx][ny][nz]=0;
							}
							else if(ff==2&&sj+1<d[nx][ny][nz])
							{
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+1;
								sj=sj+1;
								dfs(nx,ny,nz);
								sj=sj-1;
								vis[nx][ny][nz]=0;
							}
						}
					}
				}
			}
			if(nz==3)
			{
				for(int j=0;j<3;j=j+1)
				{
					int nx=x;
					int ny=y-xyb[j];
					if(nx>=1&&nx<=n-1&&ny>=1&&ny<=m-1&&vis[nx][ny][nz]==0)
					{
						int f=1;
						for(int k=0;k<xyb[j];k=k+1)
						{
							if(a[nx][ny+k]==1)
							{
								f=0;
								break;
							}
						}
						if(f==0)
						{
							break;
						} 
						if(f==1)
						{
							int ff=0;
							if(abs(z-nz)==2)
							{
								ff=1;
							}
							else if(z==nz)
							{
								ff=2;
							}
							if(ff==1&&sj+3<d[nx][ny][nz])
							{		
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+3;
								sj=sj+3;
								dfs(nx,ny,nz);
								sj=sj-3;
								vis[nx][ny][nz]=0;
							}
							else if(ff==0&&sj+2<d[nx][ny][nz])
							{
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+2;
								sj=sj+2;
								dfs(nx,ny,nz);
								sj=sj-2;
								vis[nx][ny][nz]=0;
							}
							else if(ff==2&&sj+1<d[nx][ny][nz])
							{
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+1;
								sj=sj+1;
								dfs(nx,ny,nz);
								sj=sj-1;
								vis[nx][ny][nz]=0;
							}
						}
					}
				}
			}
			if(nz==4)
			{
				for(int j=0;j<3;j=j+1)
				{
					int nx=x-xyb[j];
					int ny=y;
					if(nx>=1&&nx<=n-1&&ny>=1&&ny<=m-1&&vis[nx][ny][nz]==0)
					{
						int f=1;
						for(int k=0;k<xyb[j];k=k+1)
						{
							if(a[nx+k][ny]==1)
							{
								f=0;
								break;
							}
						}
						if(f==0)
						{
							break;
						}
						if(f==1)
						{
							int ff=0;
							if(abs(z-nz)==2)
							{
								ff=1;
							}
							else if(z==nz)
							{
								ff=2;
							}
							if(ff==1&&sj+3<d[nx][ny][nz])
							{		
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+3;
								sj=sj+3;
								dfs(nx,ny,nz);
								sj=sj-3;
								vis[nx][ny][nz]=0;
							}
							else if(ff==0&&sj+2<d[nx][ny][nz])
							{
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+2;
								sj=sj+2;
								dfs(nx,ny,nz);
								sj=sj-2;
								vis[nx][ny][nz]=0;
							}
							else if(ff==2&&sj+1<d[nx][ny][nz])
							{
								vis[nx][ny][nz]=1;
								d[nx][ny][nz]=sj+1;
								sj=sj+1;
								dfs(nx,ny,nz);
								sj=sj-1;
								vis[nx][ny][nz]=0;
							}
						}
					}
				}
			}
		}
	}
}
int main()
{
	memset(d,0x3f3f3f3f,sizeof(d));
	cin>>n>>m;
	int ffff=0;
	for(int i=1;i<=n;i=i+1)
	{
		for(int j=1;j<=m;j=j+1)
		{
			int x;
			cin>>x;
			
			if(x==1)
			{
				ffff=1;
				a[i][j]=1;
				a[i-1][j]=1;
				a[i][j-1]=1;
				a[i-1][j-1]=1;
			}
		}
	}
	cin>>qx>>qy>>zx>>zy;
	char c;
	int z;
	cin>>c;
	if(c=='E')
	{
		z=1;
	}
	if(c=='S')
	{
		z=2;
	}
	if(c=='W')
	{
		z=3;
	}
	if(c=='N')
	{
		z=4;
	}
	vis[qx][qy][z]=1;
	if(ffff==0)
	{
		cout<<32;
	}
	else
	{
		dfs(qx,qy,z);
	}
	if(fff==1&&ffff==1)
	{
		cout<<ans<<endl;
	}
	else if(fff==-1&&ffff==1)
	{
		cout<<-1;
	}
}

7-3 小源爱写题

小源现在想要加训。
他准备写 n 道题目来提高自己的算法能力。
他决定分天数(至少 2 天)完成这 n 道题目,并且每天都需要写正整数道题目。
为了提高训练效果,他规定每天写的题目数必须比上一天写的多。

输入格式:

一行一个整数,代表 n(5≤n≤500) 。

输出格式:

一个整数表示小源写完这 n 道题的所有可能方案数。

输入样例:

212

输出样例:

在这里给出相应的输出。例如:995645335

1.思路:这是一道动态规划题(好难)。我们定义状态“天数/当前总共完成的题数/前一天完成的题数”,我们可以发现天数在这道题中并不会影响总方案数(因为我们定义了状态:前一天的做题量)。另外我们求的转移方程是f[i][j]+=f[i-j][k],其中的k表示在做i-j道题时,前一天的做题数,虽然k不是我们定义的状态,但缺少了k就缺少了关键信息,所以必须有k这一层循环。

2.代码:

#include <bits/stdc++.h>
using namespace std;
long long f[505][505];
long long ans;
int main()
{
    int n;
    cin>>n;
    f[0][0]=1;
    for(int i=1;i<=n;i=i+1)
    {
        for(int j=1;j<=i;j=j+1)
        {
            for(int k=0;k<j;k=k+1)
            {
                f[i][j]=f[i][j]+f[i-j][k];
            }
        }
    }
    for(int j=0;j<=n;j=j+1)
    {
        ans=ans+f[n][j];
    }
    cout<<ans-1;
}

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值