【c/c++算法刷题笔记】—— 洛谷闯关1.5


【前言】今天继续洛谷闯关,感觉小白进化为小灰啦! 继上次做了一道迷宫题之后,对迷宫题有了执念,这几天可能闯关各种类型的迷宫题哈哈哈哈哈哈哈

P1605 迷宫

题目背景

给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

笔记
  1. 读题可知,用深度优先算法。以下是我自用的深度优先算法模板(伪代码):
const int N=10;  //根据题目条件确定数组大小
int nums[N];  // 原数组 可有可无
int result[N]; 	//保存最后结果 可有可无
int used[N]={0};		// 是否被用过 必须有

void dfs(int count){
	// 出口
	if(count==4){
		根据题目要求,对result处理
	}
	//入口 
	for(int i=0;i<4;i++){ //假设结果为4个子项
		if(used[i]==0){ //如果i未遍历,置1
			used[i]	= 1;
			result[count]=i+1;	// 结果下标为 count,count从1->4
			dfs(count+1); 	//递归
			used[i]=0;		//恢复,以便下次使用
		}
	}	
}
int main(){
	dfs(0);
	return 0;
}
//(感谢黄焖鸡学长大力支持)
  1. 一定要先确定好数据结构,比如这道题,障碍结点完全可以用二维数组标记出来,单独写一个vector反而更复杂
  2. 利用dx,dy数组打表的思想,虽阅读性减弱,但大大简化了代码量,是个好操作

/*
输入格式
第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。
输出格式
给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。
*/

#include<iostream>
#include<vector>
#include<utility>
using namespace std;

int n,m,t,sx,sy,fx,fy,ans=0;
int used[6][6]={0};	//保存 用过 的节点 和障碍节点,我直接写一起了,其实写成两个更容易理解	
vector<pair<int,int> > v_r; 	//保存 结果路径,这道题没问,大可不必写
pair<int,int> t_p;		//临时 pair
int dx[4]={-1,0,1,0};	// 打表 新学的,原本我是把四个循环都写出来了
int dy[4]={0,-1,0,1};
bool isinArea(int x,int y){ 	//判断是否出界,写进去太乱了才写出来,无所谓
	if(x>0&&x<=n&&y>0&&y<=m)return true;
	return false;
} 
void dfs(int x,int y){
//		flag=true;    这部分是之前的版本,大可不必
		//出口1  遇障碍 
//		for(int i=0;i<v_h.size();i++){
//			if(x==v_h[i].first&&y==v_h[i].second){
//				flag=false;
//				break;
//			} 
//		}
//		if(!flag) break;
	
	//出口
	if(x==fx&&y==fy) {
		ans++;
//		int k=v_r.size()-1; //为了让自己看看结果,相当于手动debug,大可不必
//		cout<<"<"<<v_r[k].first<<","<<v_r[k].second<<">"<<"ans: "<<ans<<endl;
		return;	 //返回,继续
	}
	//第一次 
	used[x][y]=1;
	for(int i=0;i<4;i++){
		if(used[x+dx[i]][y+dy[i]]==0&&isinArea(x+dx[i],y+dy[i])){
			used[x+dx[i]][y+dy[i]]=1;
			t_p.first=x+dx[i]; t_p.second=y+dy[i];
			v_r.push_back(t_p); 
			dfs(x+dx[i],y+dy[i]); 
			used[x+dx[i]][y+dy[i]]=0;
		}
	}
	used[x][y]=0;
}
int main(){
	while(cin>>n>>m>>t){
		cin>>sx>>sy>>fx>>fy;
		int x,y; 
		for(int i=0;i<t;i++){
			cin>>x>>y;
			used[x][y]=1;
		}
		dfs(sx,sy);
		cout<<ans<<endl;
	}
	return 0;
}

P1098 字符串的展开

题目描述

在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d-h”或者“4-8”的字串,我们就把它当作一种简写,输出时,用连续递增的字母或数字串替代其中的减号,即,将上面两个子串分别输出为“defgh”和“45678"。在本题中,我们通过增加一些参数的设置,使字符串的展开更为灵活。具体约定如下:

(1) 遇到下面的情况需要做字符串的展开:在输入的字符串中,出现了减号“-”,减号两侧同为小写字母或同为数字,且按照ASCII码的顺序,减号右边的字符严格大于左边的字符。

(2) 参数p1:展开方式。p1=1时,对于字母子串,填充小写字母;p1=2时,对于字母子串,填充大写字母。这两种情况下数字子串的填充方式相同。p1=3时,不论是字母子串还是数字字串,都用与要填充的字母个数相同的星号“*”来填充。

(3) 参数p2:填充字符的重复个数。p2=k表示同一个字符要连续填充k个。例如,当p2=3时,子串“d-h”应扩展为“deeefffgggh”。减号两边的字符不变。

(4) 参数p3:是否改为逆序:p3=1表示维持原来顺序,p3=2表示采用逆序输出,注意这时候仍然不包括减号两端的字符。例如p1=1、p2=2、p3=2时,子串“d-h”应扩展为“dggffeeh”。

(5) 如果减号右边的字符恰好是左边字符的后继,只删除中间的减号,例如:“d-e”应输出为“de”,“3-4”应输出为“34”。如果减号右边的字符按照ASCII码的顺序小于或等于左边字符,输出时,要保留中间的减号,例如:“d-d”应输出为“d-d”,“3-1”应输出为“3-1”。

笔记
  1. 这道题可不用改变原字符串,直接输出,这样就更容易了。
  2. p1,p2,p3 有多种组合情况时,要考虑怎么能减少比较的次数,先判断谁后判断谁。此题p1 和填充内容有关,p2和重复输出有关,p3表示是否反着输出,而是否 反着输出 表现在输出的循环上,p1,p2写在循环里。先比较p1,确定输出的内容,之后输出p2次
  3. 遇到‘-’,要么输出‘-’,要么输出隐藏 的字母或数字。
  4. 如果p1==1时,不管是字母还是数字

#include<iostream>
#include <string>
using namespace std;

const int mns='A'-'a'; //大小写的 差值  
int p1,p2,p3;
char low,high,temp,j;	
int main(){
	while(cin>>p1>>p2>>p3){
		string s;
		cin>>s;
		for(int i=0;i<s.size();i++){	
			low=s[i-1];high=s[i+1];
			if((s[i]=='-')&&(low<high)&&((low>='0'&&high<='9')||(low>='a'&&high<='z'))){				
				for(p3==1?j=low+1:j=high-1;p3==1?j<high:j>low;p3==1?j++:j--){
					if(p1==1) temp=j;
					else if(p1==2) temp=j>='a'?j+mns:j;
					else temp='*';
					for(int k=0;k<p2;k++)	// 只要确定数量!用for
						 cout<<temp;	
				}
			}
			else cout<<s[i];
		}
	}	
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值