第一次csp模拟 C路径搜索

题意:
在一个而无限大的区域内,有一点向外辐射路径。题目给出路径分裂多少次和每次路径的长度。每一次路径分裂后,变成两条路径,分别在原来路径的逆时针45°和顺时针45°的地方,继续走。最后输出所有路径一共经过多少的点。(具体的图像贴在最后面)


思路:
即首先申请一个二维数组,考虑到题目中最多分裂30次,每次的路径小于等于5,则可开辟300*300应该够用,或者可以稍微再大点。之后考虑到路径不断分裂并且方向转换的情况,可将起点放在矩阵中心,定义两个数组x[8]和y[8]记录运动方向。根据分裂时的方向,进行加减便得到下一轮的分裂开的两个路径方向。每到达一个点,判断是否被标记过,如果没有被标记,则进行标记,并且到达的点数count加1。再递归进入下一轮遍历。其中递归时,传入当前所在的点坐标x,y和路径的方向(由上一轮给出以及是第几次分裂)。 当然,仅仅这样搜索肯定是过不了的,时间开销太大。(。此处剪枝没想到,请教的大佬。) 在仔细看这个遍历路径的过程,其实就是深度搜索的一种。由于向左和向右的两个分裂在遍历中会有许多重复的判断,会浪费很多开销。(比如先向左的的遍历过了,在下一轮中向右后遍历会继续对左边的的进行判断,在此处可以进行剪枝了)。 在同一层次,即同样的分裂次数(即确定了分裂的步长),在相同的点,有一个相同方向的分裂,此后这一点之后的所有状态都是一样的了,即不需要再进行遍历,可在此处进行剪枝,即可用一个四维的数组分别记录下这四个状态,进行一个标记。最后得出的路径长度即为所需要的路径的长度。


总结:
磁体主要是一个深搜的实现过程,但有很多需要考虑的地方。比如,通过数据来确定数组的大小等等,其中对深搜的剪枝方向的要求很大。还有数据较大们也要考虑各处的数据的开销,比如一开始用的int数组标记,直接就爆了,后来换成bool的就过了。还有就是在递归的时候,如dfs((dir+1)%8,num+1,x,y); 这个式子中,不能对num实行num++和++num的操作,会改变num的值,使递归最后得到的路径会有跳跃的改变。


代码:

#include <iostream>
#include <stdio.h>
using namespace std;


int a[8]={0,-1,-1,-1,0,1,1,1};
int b[8]={1,1,0,-1,-1,-1,0,1};

bool ma[600][600];  //坐标矩阵 
bool ret[600][600][30][8]={0}; //参数分别为x,y第几次分裂,分裂方向
int count=0;  //到达的点数量
int n=0;  //分裂次数
int step[30]; //每次分裂的步长 

void dfs(int dir, int num,int x, int y){ //方向,第几次分裂,横纵坐标 
	if(ret[x][y][num][dir]==1 || num>n-1) return;   //第num次在这点已经出现,说明之后的状态完全一样
	ret[x][y][num][dir]=1;  //记录该点
	for(int i=0; i<step[num];i++){
		x+=a[dir];
		y+=b[dir];
		if(!ma[x][y]){  //该点没有到达过,进行标记和数量增加
			ma[x][y]=1;
			count++;
		}
	} 
	dfs((dir+1)%8,num+1,x,y);  //向逆时针分裂
	dfs((dir+7)%8,num+1,x,y);  //向着顺时针分裂
} 

int main(){
	
	cin>>n;
	for(int i=0; i<n;i++){  //记录各个步数
		cin>>step[i];
	}
	
	int dir=0; //方向 
	int x=300;  //起点 
	int y=300;
	int num=0;  //分裂次数 
	dfs(dir,num,x,y);  
	cout<<count<<endl;
	
	return 0;
}

原题:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值