算法笔记 书中的样例源码

2 篇文章 0 订阅
1 篇文章 0 订阅

算法笔记 胡凡.书中的样例源码.

**这些代码都是在Dev C++ 中跑的.可以复制就用上,提供给有算法笔记这本书的同学来测试书中的代码 不过后来我去买yxc的课了. 回头看这些代码有些呆和长 C++ 特性页没用上 所以去买课吧哈哈哈 acwing **
在这里插入图片描述
目前只有这些.上个学期课余时间抄录的.难免有一些纰漏.也希望大家帮我挑挑错.

2

2.2.6,常用math函数

#include<cstdio>
#include<math.h>

//变量取绝对值
int test1()
{
	double db = -12.56;
	printf("%.2f\n", fabs(db));
	return 0;
}

//向上取整,向下取整
int test2()
{
	double db1 = -5.2, db2 = 5.2;
	printf("汉字%.0f %.0f \n", floor(db1), ceil(db1));
	printf("%.0f %.0f\n,", floor(db2), ceil(db2));
	return 0;
}

//该函数用于返回r的p次幂  求r的p次方 
int test3()
{
	double db = pow(2.0, 3.0);;
	printf("%f\n", db);
	return 0;
}

//该函数用于返回double类型的算术平方根.
int test4()
{
	double db = sqrt(2.0);
	printf("%f\n", db);
	return 0;
}

//该函数用于返回double型变量的以自然数对数为底的对数
int test5()
{
	double db = log(1.0);
	printf("%f\n", db);
	return 0;
}

/*
sin(double x),cos(double x),tan(double x) 返回正弦值等,要求是弧度制
asin(double x),acos(double x),atan(double x) 返回反正弦值等,要求是弧度制
*/

const double pi = acos(-1.0);

int test6()
{
	double db1 = sin(pi * 45 / 180);
	double db2 = cos(pi * 45 / 180);
	double db3 = tan(pi * 45 / 180);
	printf("%f,%f,%f\n", db1, db2, db3);
	return 0;
}
//返回double型变量的反正弦值 ... 
int test7()
{
	double db1 = asin(1);
	double db2 = acos(-1.0);
	double db3 = atan(0);
	printf("%f,%f,%f\n", db1, db2, db3);
	return 0;
}

// 将double类型四舍五入,返回类型也是double 需要进行取整.
int test8()
{
	double db1 = round(3.40);
	double db2 = round(3.45);
	double db3 = round(3.50);
	double db4 = round(3.55);
	double db5 = round(3.60);
	printf("%d, %d, %d, %d, %d\n", (int)db1, (int)db2, (int)db3, (int)db4, (int)db5);
	return 0;
}

int main()
{
	test8();
}

2.5.2 冒泡排序

//通过n-1轮的排序每次都把最大的挪走到最后一个位置来完成n个元素的排序..
#include<stdio.h>
int main()
{
	int a[10] = { 3,1,4,5,2 };
	for (int i = 1; i <= 4; i++)//进行n-1趟排序
	{
		for (int j = 0; j < 5 - i; j++)
		{
			if (a[j] > a[j + 1]) 
			{
				int temp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = temp;

			}
		}
	}
	for (int i = 0; i < 5; i++)
	{
		printf("%d", a[i]);

	}
	return 0;
}

2.5.4 memset

//对数组中每一个元素赋相同的值,仅仅可以赋值0或者-1.其他的值可以用fill函数来赋值.
#include<stdio.h>
#include<string.h>//需要这个头文件.<iostream>里面包括了
int main()
{
	int a[5] = { 1,2,3,4,5 };
	//赋值0
	memset(a, 0, sizeof(a));
	for (int i = 0; i < 5; i++)
		printf("%d", a[i]);
	printf("\n");
	//赋值-1
	memset(a, -1, sizeof(a));
	for (int i = 0; i < 5; i++)
		printf("%d", a[i]);
	printf("\n");
	return 0;
}

2.5.5 字符数组

#include<stdio.h>

//scanf输入printf输出;
int test3() {
	char str[10];
	char s;
	//scanf("%s", str);//%s识别到空格和换行就结束一个字符串输入了%c能够识别空格和换行将其输入.
	//printf("%s", str);
	scanf("%c", &s);
	printf("%c", s);

	return 0;
}

//%c的补足.只能是单个字符不能是字符数组.



//getchar输入putchar输出  //用来输入和输出单个字符.
int test4()
{
	char str[5][5];
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			str[i][j] = getchar();
		}
		getchar();//这句未来吧输入中每行末尾的换行符号吸收掉./
	}
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++) {
			putchar(str[i][j]);
		}
		putchar('\n');
	}
	return 0;
}




//gets输入,puts输出/gets是输入一行字符串的.有时候他和scanf有点矛盾.你猜吧
//vs2019里一个源程序文件里若前面有scanf的输入语句时
//后面的gets_s()是不起任何作用的 getchar来吃掉一个换行符号 
int test5() {
	char str1[20];
	char str2[5][10];
	
	gets_s(str1);
	for (int i = 0; i < 3; i++)
	{
		gets_s(str2 [i]);
	}
	puts(str1);
	for (int i = 0; i < 3; i++)
	{
		puts(str2[i]);
	}
	return 0;
}

int main()
{
	test5(); 
}

//特别提醒:如果开字符数组.大小要比目的数量多至少一个.
//用getchar 输入字符切记要给结尾增加一个"\0"; 

2.5.6string.h头文件

#include<stdio.h>
#include<string.h>
//1.strlen()得到字符数组中第一个\0前面的字符的个数
//就是返回.字符串长度 
int test6()
{
	char str[10];
	gets_s(str);
	int len = strlen(str);
	printf("%d\n", len);
	return 0;
}


/*
2.strcmp()比较两个字符串大小通过减法操作.
返回值是负数说明小于
返回0说明等于
返回正数说明大于.*/ 
int test7() {
	char str1[50], str2[50];
	gets_s(str1);
	gets_s(str2);
	int cmp = strcmp(str1, str2);
	if (cmp < 0)printf("str1 < str2");
	else if (cmp > 0)printf("str1 > str2");
	else printf("str1==str2");
	return 0;
}

//3.strcpy 把字符数组2复制给字符数组1

int test8()
{
	char str1[50], str2[50];
	gets_s(str1);
	gets_s(str2);
	strcpy(str1, str2);
	puts(str1);
	return 0;
}

//4.strcat 把一个字符串接到另一个字符串后面
int test9()
{
	char str1[50], str2[50];
	gets_s(str1);
	gets_s(str2);
	strcat(str1, str2);
	puts(str1);
	return 0;
}
int main()
{
	test9();
} 

2.5.7 sscanf与sprintf

//sscanf and sprintf 可以理解为string + scanf ,和string + printf 

/*
scanf("%d",&n);
printf("%d",&n);
等价于
scanf(screen,"%d",&n);
printf(screen,"%d",&n);

sscanf(str,"%d,&n");从左至右(把左边的str里的值 给了右边的n里面.) 
sprintf(str,"%d,n");从右至左(把右边n里面的东西.给了左边str里面.) 

*/
#include<cstdio> 
int test1() {
	int  n;
	char str[100] = "123";
	sscanf(str, "%d", &n);
	printf("%d", n);
	return 0;
}
int test2() {
	int n = 233;
	char str[100];
	sprintf(str, "%d",n);
	printf("%s\n", str);
	return 0;
}

/*
同时也可以进行复杂的格式输入和输出

char str[100] = "2048:3.14,hello",str2[100];
sscanf(str,"%d:%lf,%s", &n,&db, str2);  //把str里面的东西叉开 然后分别存进右边的变量 

*/ 
int main()
{
	test1();
}
 

3

3.1 简单模拟 PAT B1001

/*#include<stdio.h>

int main()
{
    int n;
    int j = 0;
    scanf("%d\n",&n);
    while(n!=1)
    {
        j++;
        if(n%2 == 0)//错误1.判断里面不应该是两个等号吗. 
            n=n/2;
        else
            n = (3*n+1)/2;//错误二,居然把乘号忘记了 
    }
    printf(" 从n到1尽经历了 %d 次运算",j);
        //莫名其妙输出不出来.. 好吧来瞅瞅正确答案 
}
*/ 

#include<cstdio>

int main()
{
    int n,step = 0;
    printf("狗日的输出啊"); 
    scanf("%d\n",&n);
    while(n!=1)
    {
        if(n%2 == 0) 
            n = n/2;
        else 
            n = (3*n+1)/2;
        step++;
    }
    printf("出来了(出不来..) %d\n",step);
    return 0; 
}

3.1 简单模拟 PAT B1032

#include<cstdio>

const int maxn = 10010;
int school[maxn] = {0};    //记录每个学校的总分
int main(){
    int n,schID,score;
    scanf("%d",&n);
    for(int i = 0;i<n;i++)
    {
        scanf("%d %d", &schID,&score);   //学校的 ID 分数
        school[schID] +=score;     //学校schID的总分增加score
    }
    int k = 1,MAX = -1;           //最高学校的ID和总分
    for(int i = 1;i<=n;i++)
    {
        if(MAX < school[i]){
            MAX = school[i];
            k = i;
        }
    }
    printf("%d %d\n",k,MAX);
    return 0;
}

3.2 查找元素 codeup 1934找x

#include<cstdio>
int main(){
	int a[100];
	int n,x ,i;
	scanf("%d",&n);
	for(int i = 0;i<n;i++){
		scanf("%d",&a[i]);//数组也要取地址符号啊.我以为都不用呢. 
	}
	scanf("%d",&x);
	for(i = 0;i<n;i++){
		if(a[i]==x)
		{
			printf("%d\n",i);
		//	break; 
		} 
//		else if(i == n)
//		printf("-1\n");   在里面就不行.超出范围也不显示负一呢. 
	}
 	if(i == n)
		printf("-1\n"); 

} 

3.3图形输出

#include<cstdio>
int main(){
	int row,col;
	char c;
	scanf("%d %c",&col, &c);  //输入列数,和想要使用的字符 
	if(col%2==1)row = col/2+1;
	else row = col/2;
	//第一行
	for(int i = 0;i<col;i++){
		printf("%c",&c);
	} 
	printf("\n");
	//第2行到row-1行
	for(int i = 2;i<row;i++){
		printf("%c",c);
		for(int j = 0;j<row;i++){
			printf(" ");//col-2个空格. 
		}
		printf("%c\n",c);
	} 
	
	//第row行
	for(int i = 0;i<col;i++){
		printf("%c",c);
	} 
	return 0;
	
} 

3.4日期差值

#include<cstdio>

int month[13][2] = {//平年闰年天数 
	{0,0},{31,31},{28,19},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{31,30},{31,31}
};
bool isLeap(int year) {
	return(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main1() {
	int time1, y1, m1, d1;
	int time2, y2, m2, d2;
	while (scanf_s("%d%d", &time1, &time2) != EOF) {//EOF是啥.. 
		if (time1 > time2) {
			int temp = time1;
			time1 = time2;
			time2 = temp;
		}
		y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
		y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;
		int ans = 1;//记录结果.
		//第一个日期没有达到第二个日期时候进行循环.
//		既!((y1 == y2)&&(m1 == m2)&&(d1 == d2)) 
		while (y1 < y2 || m1 < m2 || d1 < d2) {
			d1++;
			if (d1 == month[m1][isLeap(y1)] + 1) {//满了当月天数 
				m1++;//     这嘎达抄错了..
				d1 = 1;
			}
			if (m1 == 13) {//月份满12 
				y1++;
				m1 = 1;
			}
			ans++;
		}
		printf("%d\n", ans);
	}
	return 0;
}

3.5进制转换

#include<cstdio>


//将p进制数x转换成十进制
/*
int y = 0,
int product = 1;//product在循环中会不断乘P得到,1,p,p^2,p^3;
int x;
while (x!= 0) {
	y = y + (x % 10) * product;
	x = x / 10;
	product = product * P;
}
*/

//将十进制数y转换为Q进制数z 采用除基取余法
/*
int z[40], num = 0;
do {
	z[num++] = y % Q;
	y = y / Q;
} while (y != 0);//y等于零的时候也能执行一次存入z[0]=0
*/


int main(){
	int a,b,d;
	scanf("%d%d%d",&a,&b,&d);
	int sum = a+b;
	int ans[31],num = 0;
	do{
		ans[num++] = sum%d;
		sum/=d;
	}while(sum!=0);
	for(int i = num-1;i>=0;i--){
		printf("%d",ans[i]);
	}
	return 0;
}

3.6 PAT B1009

#include<cstdio>
#include<cstring>
int main(){
	char str[90];
	gets(str);
	int len = strlen(str),r = 0,h = 0;//r为行,h为列
	char ans[90][90];
	for(int i = 0;i<len;i++){
		if(str[i] != ' '){
			ans[r][h++] = str[i];
		}else{
			ans[r][h] = '\0';
			r++;
			h = 0;
		}
	} 
	for(int i = r;i>=0;i--){	//倒着输出单词即可 
		printf("%s",ans[i]);
		if(i>0) printf(" ");
	}
	return 0;
}

3.6字符串处理

#include<cstdio>
#include<cstring>
const int maxn = 256;
//判断字符串是否为回文串
bool judge(char str[]) {
	int len = strlen(str);
	for(int i = 0;i<len/2;i++){ 	//i枚举字符串的前一半 
		if(str[i] != str[len-1-i]){
			return false;
		} 
	}
	return true;
}
int main(){
	char str[maxn];
	while(gets(str)){
		bool flag = judge(str);
		if(flag==true){
			printf("YES\n");
		}else{
			printf("NO\n");
		}
	}
	return 0;
}

4

4.1.1选择排序

//每次找到数组中最小元素.与最前面的交换..然后遍历范围缩减...
#include<stdio.h>

int A[] = { 3,1,4,5,2 };
int n =  sizeof(A)/sizeof(int); 
	
void selectSort(){
	for (int i = 0; i <= n; i++)//进行n趟操作 
	{
		int k = i; //中间变量 
		for (int j = i; j <= n; j++)//选出[i,n]的最小元素 
		{
			if (A[j] < A[k]) 
			{
				k = j; 
			}
		}
		//交换两个值 
		int temp = A[i];
		A[i] = A[k];
		A[k] = temp;
	}
} 

int main()
{
	selectSort(); 
	for (int i = 0; i < n; i++)
	{
		printf("%d", A[i]);
	}
	return 0;
}

4.1.3 排序题 sort的应用 PAT A1025

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Student{
	char id[15];  //准考证号 
	int score;		//分数 
	int location_number;	//考场号 
	int local_rank;		//考场内排名 
}stu[30010];

bool cmp(Student a,Student b){
	if(a.score != b.score) return a.score> b.score;// 先按分数从高到底排序
	else return strcmp(a.id,b.id)<0 ;//分数相同按照准考证号从小到大排序 
}

int main(){
	int n,k,num = 0;		//num为总考生数量 
	scanf("%d",&n);			//考场数 
	for (int i = 1;i<=n ;i++)
	{
		scanf("%d",&k);				//该考场内的人数 
		for(int j = 0;j<k;j++){
			scanf("%s %d",stu[num].id,&stu[num].score);
			stu[num].location_number = i;		//考场号为i 
			num++;								//总考生数量加1 
		}
		sort(stu + num -k,stu+num,cmp);			//将该考场的考生排序 
		stu[num-k].local_rank = 1;				//该考场第一名的local rank计算为1; 
		for(int j = num-k+1;j<num;j++) {		//剩余的考生. 
			if(stu[j].score==stu[j-1].score){	//如果与前一位考生同分.
				//local_rank也相同. 
				stu[j].local_rank = stu[j-1].local_rank;
			}else{
				// local_rank为该考生前的人数. 
				stu[j].local_rank = j+1-(num-k);
			}
		}
	}
	printf("%d\n",num);//输出总考生数量. 
	sort(stu,stu+num,cmp);
	int r = 1;
	for(int i = 0;i<num;i++) {
		if(i>0&&stu[i].score != stu[i-1].score){
			r = i+1;		//考生与上一个分数不同的时候让r跟新人数. 
		}
		printf("%s ",stu[i].id);
		printf("%d %d %d\n",r,stu[i].location_number,stu[i].local_rank);
	}
	return 0;
} 

4.1.3插入排序

//将待插入的元素一个个插入到初始已经有序部分.遵循使插入后保持有序的原则 
#include<stdio.h>

int A[] = { 3,1,4,5,2 };
int n =  sizeof(A)/sizeof(int); 
	
void insertSort(){
	for (int i = 1; i <= n; i++)//进行n -1 趟排序 
	{
		int temp = A[i] ,j = i; //中间变量 临时存放A[i] j从i 开始向前枚举 
		while(j > 0 && temp < A[j-1])//只要temp小于前一个元素  
		{
			A[j] = A[j-1];
			j --;
		}
		
		A[j] = temp;
	}
} 

int main()
{
	insertSort(); 
	for (int i = 0; i < n; i++)
	{
		printf(" %d", A[i]);
	}
	return 0;
}

4.4.1 简单贪心 PAT B1023组个最小数

#include<cstdio>
int main(){
	int count[10];
	for(int i = 0;i<10;i++){
		scanf("%d",&count[i]);
	}
	for(int i = 1;i<10;i++){
		if(count[i]>0){
			printf("%d",i);
			count[i]--;
			break;
		}
	}
	for(int i = 0;i<10;i++){
		for(int j = 0;j<count[i];j++){
			printf("%d",i);
		}
	}
	return 0;
} 
//2 2 0 0 0 3 0 0 1 0 

4.4.1 简单贪心PAT B1020月饼

#include<cstdio>
#include<algorithm>
using namespace std;
struct mooncake{
	double store;
	double sell;
	double price;
}cake[1010]; 

bool cmp(mooncake a,mooncake b){
	return a.price>b.price;
}
int main()
{
	int n;
	double D;
	scanf("%d%lf",&n,&D);
	for(int i =0;i<n;i++){
		scanf("%lf",&cake[i].store);
	}
	for(int i =0;i<n;i++){
		scanf("%lf",&cake[i].sell);
		cake[i].price = cake[i].sell/cake[i].store;
	} 
	sort(cake,cake+n,cmp);//按单价从高到低排序.
	double ans = 0;
	for(int i = 0;i<n;i++){
		if(cake[i].store<=D){
			D-=cake[i].store;
			ans+=cake[i].sell;
		}else{
			ans+=cake[i].price*D;
			break;
		}
	}
	printf("%.2f\n",ans); 
	return 0;
}

/*3 20
18 15 10  没弄出来.. 
75 72 45*/

4.4.2区间贪心

//给出N个开区间.(x,y)从中尽可能选择多的开区间.使得这些开区间两两没有交集.
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn1 = 110;
struct Inteval {
	int x, y;//开区间左右端点.
}I[maxn1];
bool cmp(Inteval a, Inteval b) {
	if (a.x != b.x) return a.x > b.x;
	else return a.y < b.y;
}
int main() {
	int n;
	while (scanf("%d", &n), n != 0) {
		for (int i = 0; i < n; i++) {
			scanf("%d%d", &I[i].x,&I[i].y);
		}
		sort(I, I + n, cmp);//把区间排序.
		//ans记录不相交区间个数,lastX记录上一个被选中区间的左端点.
		int ans = 1, lastX = I[0].x;
		for (int i = 1; i < n; i++) {
			if (I[i].y <= lastX) {
				lastX = I[i].x;
				ans++;
			}
		}
		printf("%d\n", ans);

	}
	return 0;
}

4.5.2二分查找

#include<cstdio>
//二分区间为左闭合右闭合的[left,right],传入的处置为[0,n-1]
int binarySearch(int A[],int left,int right,int x){
	int mid; 
	while(left<=right){
		mid = (left+right)/2; 
		if(A[mid]==x)return mid;
		else if(A[mid]>x){
			right = mid-1;
		}else{
			left = mid+1;
		}
	}
	return -1;//查找失败返回-1 
} 

//1
int lower_bound(int A[],int left,int right,int x){
	int mid;
	while (left<right){
		mid = (left+right)/2;
		if(A[mid]>=x){
			right = mid;
		}else{
			left = mid+1;
		}
	}
	return left;
} 

//2
int upper_bound(int A[],int left,int right,int x){
	int mid;
	while (left<right){
		mid = (left+right)/2;
		if(A[mid]>x){
			right = mid;
		}else{
			left = mid+1;
		}
	}
	return left;
} 

//二分法拓展,

// 根号二的近似值 
const double eps = 1e-5;//精度为10^-5
double f(double x){
	return x*x;
} 
double calSqrt(){
	double left = 1,right = 2,mid;
	while(right-left>eps){
		mid = (left+right)/2; 
		if(f(mid)>2){						//mid
			right = mid;//往左子区间[left mid]查找 
		}else{
			left = mid;
		}
	}
	return mid; 
}


int main(){
	const int n= 10;
	int A[n] = {1,2,3,6,7,8,10,11,12,15};
	printf("%d %d\n",binarySearch(A,0,n-1,6),binarySearch(A,0,n-1,9));
	
	//第一小问.求序列第一个大于等于x元素的位置l 
	printf("%d\n",lower_bound(A,0,n-1,6));
	//第二小问.求序列第一个大于x元素的位置l 
	printf("%d\n",upper_bound(A,0,n-1,6));
	printf("%f\n",calSqrt());
	 
	return 0;
}



/*
寻找有序序列总第一个满足条件的元素位置,问题的固定模板.
二分区间为左闭右闭[left right] 
初值必须能覆盖所有可能取值并且left 比最小取值小1 
int solve(int left,int right){
	int mid;
	while (left<right){  //对于左闭右闭  left+1<right 意味着唯一位置. 
		mid = (left+right)/2;
		if(条件成立){
			right = mid;//往左子区间[left mid]查找 
		}else{
			left = mid+1;
		}
	}
	return left;
} 

二分区间为左开右闭(left right] 

int solve(int left,int right){
	int mid;
	while (left+1<right){  //对于左开右闭(left right]   left+1<right 意味着唯一位置. 
		mid = (left+right)/2;
		if(条件成立){
			right = mid;//往左子区间[left mid]查找 
		}else{
			left = mid;
		}
	}
	return right;
} 

*/

4.5.3快速幂

//给定三个正数.a,b,m(a<10^6,b<10^6,1<m<10^9) 求a^b%m.

//时间复杂度O(b) 
typedef long long LL;
LLpow (LL a,LL b,LL m){
	LL ans = 1;
	for(int i = 0;i<b;i++){
		ans = ans*a%m;
	}
	return ans;
} 


//时间复杂度O(logb)ku快速幂 的递归写法. 
LL binaryPow(LL a,LL b,LL m){
	if(b==0) return 1;
	//b为奇数转换为b-1 
	if(b%2==1) return a*binaryPow(a,b-1,m)%m;
	//b为偶数转换为 b/2 
	else{
		LL mul = binaryPow(a,b/2,m);
		return mul*mul%m; 
	} 
} 

//迭代写法
LL binaryPow(LL a,LL b,LL m){
	LL ans = 1;
	while(b>1){
		if(b&1){	//如果二进制末尾为1. 
			ans = ans*a%m;//令ans累计上a 
		}
		a = a*a%m; 
		b>>1;//将b的二进制右移动一位. 
	}
	return ans;
}

4.6.1two point

//在一个有序数组中找到两个和为m的一组数
while(i < j)
{
	if(a[i] + a[j] == m)
	{
		printf(" %d %d\n",i ,j);
		i ++;
		j --;
	}else if(a[i] + a[j] < m) i ++;
	else j --;
}



//把两个递增的序列合并成一个递增的序列 

int merge(int A[],int B[],int C[],int n,int m){//n,m是A,B的数组大小. 
	int i = 0,j = 0,index = 0; 		//i指向A[0] j指向B[0] 
	while (i<n&&j<m){
		if(A[i]<=B[j]){				//如果A[i]<=B[j] 将A[i]加入序列C 
			C[index++] = A[i++];
			
		}else{
			C[index++] = B[j++];  		//如果A[i]>B[j] 将B[j]加入序列C 
		}
	}
	while (i<n) C[index++] = A[i++];
	while (j<m) C[index++] = B[j++];		//把剩下的加上去.
	 
	return index; 
} 

//使用两个下标i ,j对序列进行扫描,以较低的复杂度解决问题(t p 是一种思想) 
 

4.6.2归并排序

//将序列两两分组.分成N/2个组(比如;有七个数,先分四个组.再分两个组..)组内单独排序.直到剩下一个组. 
//时间复杂度nlogn 
#include<stdio.h>
//#include<math.h> 
#include<algorithm>

using namespace std;algorithm  这俩东西再用min 的时候配套了. 

int A[] = { 66, 12, 33, 57, 27, 18 , 15 };
int n =  sizeof(A)/sizeof(int); 
const int maxn = 100; 

//将数组A 的两个连续的区间合并成有序区间.. 
int merge(int A[],int L1,int R1,int L2,int R2){
	int i = L1,j = L2; 		//i指向A[L1] j指向A[L2]
	int temp[maxn],index = 0; //temp临时存放合并后的数组.index为其下标 
	while (i <= R1 && j <= R2){
		if(A[i] <= A[j]){				//如果A[i]<=A[j] 将A[i]加入序列temp 
			temp[index++] = A[i++];
		}else{
			temp[index++] = A[j++];  		//如果A[i]>A[j] 将A[j]加入序列temp
		}
	}
	while (i <= R1) temp[index++] = A[i++];
	while (j <= R2) temp[index++] = A[j++];		//把剩下的加上去.
	
	for(int i = 0;i < index;i++) 
		A[L1+i] = temp[i];//将合并后的数组返回数组A 
	
} 


//递归实现版本 
//将array数组当前区间{left,right}进行归并排序. 
void mergeSort(int A[],int left,int right){
	if(left<right){
		int mid = (left+right)/2;
		mergeSort(A,left,mid);
		mergeSort(A,mid+1,right);
		merge(A,left,mid,mid+1,right);		 
	}
} 

// 非递归实现
void mergeSort1(int A[])
{
	//sept 为组内元素个数,step/2为左子区间元素个数,注意等号可以不取.
	for(int step = 2;step / 2 <= n;step *= 2)
	{
		//每step个元素一组,组内前step/2和后step/2个元素进行合并.
		for(int i = 1; i <= n; i += step)
		{//对每一组
			int mid = i + step / 2 - 1;		//
			if(mid + 1 <= n)
				merge(A, i, mid, mid+1 , min (i + step - 1, n)); 
			
		} 
	} 
} 

//如果题目值要求给出归并排序的每一趟结束时的序列,那可以用sort函数来代替merge函数 


//题目只要求给出每一趟结束的序列.那就不使用merge.可以直接sort 
void mergeSort2(int A[]){
	//sept 为组内元素个数,step/2为左子区间元素个数,注意等号可以不取.
	for(int step = 2;step/2<=n;step*=2){
		//每step个元素一组,组内前step/2和后step/2个元素进行合并.
		for(int i = 1;i <= n;i += step){//对每一组
			sort(A+i,A + min(i + step,n + 1)); 
		} 
		//此处可以输出归并排序的某一趟结束的序列. 
		for (int i = 0; i < n; i++)
		{ 
			printf(" %d", A[i]);
		} 
		printf("\n");
	} 
} 

int main()
{
//	mergeSort(A,0,n - 1); 
	for (int i = 0; i < n; i++)
	{
		printf(" %d", A[i]);
	}
	printf("\n");
	
	//mergeSort1(A); //输出失败.sorry 
	
	for (int i = 0; i < n; i++)
	{
		printf(" %d", A[i]);
	}
	printf("\n");
	
	return 0;
}

4.6.3快速排序

//1  A[left]是主元 

int Partition(int A[],int left,int right){
	int temp = A[left];				//将A[left]存入临时遍历temp中 
	while(left<right){
		while(left<right&&A[right]>temp) right--;//反复左移right 
		A[left] = A[right];
		while(left<right&&A[left]<=temp) left++;//反复右移left 
		A[right] = A[left];
	}
	A[left] = temp;
	return left;		//返回相遇的下标 
} 

//快速排序
void quickSort(int A[],int left,int right) {
	if(left<right) {//当前区间长度不超过1
		//将[left,right]按照A[left]一分为二
		int pos = Partition(A,left,right);
		quickSort(A,left,pos-1);
		quickSort(A,pos+1,right); 
	}
} 

//如何生成随机数.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
int main(){
	srand((unsigned)time(NULL));//必须有. 
	for(int i = 0;i<10;i++){
		printf("%d ",rand()%2);//[0,1]
	}
	printf("\n");
	for(int i;i<10;i++){
		printf("%d ",rand()%5+3);//[3,7]  (b-a+1)+a
	}
	printf("\n");
	for(int i = 0;i<10;i++){//[10000,60000] RAND_MAX常量 32767
	//(round(1.0*rand()/RAND_MAX*50000+10000)) 
		printf("%d ",(int)(round(1.0*rand()/RAND_MAX*50000+10000)));
	}
	
	return 0;
} 


//随机选取主元,对区间[left,right]进行划分.
int randPartition(int A[],int left,int right){
	//生成[left,right]内的随机数P
	int p = (round(1.0*rand()/RAND_MAX*(right-left)+left)) ;
	swap(A[p],A[left]);
	//以下为原先partition函数的划分过程. 
	int temp = A[left];				//将A[left]存入临时遍历temp中 
	while(left<right){
		while(left<right&&A[right]>temp) right--;//反复左移right 
		A[left] = A[right];
		while(left<right&&A[left]<=temp) left++;//反复右移left 
		A[right] = A[left];
	}
	A[left] = temp;
	return left;		//返回相遇的下标 
} 

5

5.6大整数运算

#include<stdio.h>			//标准输入输出
#include<string.h>			//C语言字符数组字符串


struct bign{
	int d[1000];
	int len;
	bign(){				//构造函数 
		memset(d,0,sizeof(d));//对数组全部初始化赋值0 
		len = 0;
	}
};
//把输入的字符串调整成大数的约定格式,(低位存在低位)需要逆置 
bign change(char str[]){
	bign a;
	a.len = strlen(str);//bign的长度就是字符串的长度
	for(int i = 0;i<a.len;i++){
		a.d[i] = str[a.len-i-1]-'0';//逆着赋值 
	} 
	return a; 
} 


//比较两个bign变量的大小
 

//int compare(bign a,bign b){
//	if(a.len>b.len)return 1;
//	else if(a.len<b.len)return -1;
//	else {
//		int i = a.len-1;//放在里面显示为定义i 
//		for(;i>=0;i--);//从高位向低位比较 
//		{
//			if(a.d[i]>b.d[i]) return 1; 
//			else if(a.d[i]<b.d[i]) return -1;
//		}
//		return 0;//相等 
//	}
//} 

//大整数的四则运算.
//高精度加法.
bign add(bign a,bign b){
	bign c;
	int carry = 0;//carry是进位
	for(int i = 0;i<a.len||i<b.len;i++){// 以较长的为界限 
		int temp = a.d[i] + b.d[i] +carry;//对应位于进位相加
		c.d[c.len++] = temp%10;
		carry = temp/10; //十位数为新的进位. 
	} 
	if(carry != 0){
		c.d[c.len++] = carry;
	}
	return c;
} 

//高精度减法
bign sub(bign a,bign b){
	bign c;
	for(int i = 0;i<a.len||i<b.len;i++){
		if(a.d[i]<b.d[i]){
			a.d[i+1]--;//向高位借位;
			a.d[i]+=10;//当前为加10 
		}
		c.d[c.len++] = a.d[i]-b.d[i]; 
	}
	while(c.len-1>=1&&c.d[c.len-1]==0){
		c.len--;
	}
	return c;
} 


void print(bign a){
	for(int i = a.len-1;i>=0;i++){
		printf("%d",a.d[i]);
	}
}

 
//炸了.未完单徐 
int main()
{

	char str1[1000],str2[1000];
	scanf("%s%s",str1,str2);
	bign a = change(str1);
	bign b = change(str2);
	
	print(add(a,b));

	return 0;						//返回0,不然pat报错
}

5.8.2组合数的计算

//组合数计算C(n,m)n个数中取出m个组合 

//递归代码  C(n,m)=C(n-1,m)+C(n-1,m-1)
long long C(long long n,long long m){
	if(m==0||m==n) return 1;
	return C(n-1,m)+C(n-1,m-1);
} 

//减少重复计算的递归代码

long long res[67][67] = {0};
long long C(long long n,long long m){
	if(m==0||m==n) return 1;
	if(res[n][m] != 0) return res[n][m];
	return res[n][m] = C(n-1,m)+C(n-1,m-1);
} 

//把整张表都计算出来的递推代码
const int n = 60;
void calC(){
	for(int i = 0;i<=n;i++){
		res[i][0] = res[i][i] = 1;
	}
	for(int i = 2;i<=n;i++){
		for(int j = 0;j<=i/2;j++){
			res[i][j] = res[i-1][j]+res[i-1][j-1];//递推计算c(i,j)
			res[i][j-1] = res[i][j];//C(i,i-j) = C(i,j) 
		}
	}
} 

//如何计算 C(n,m)%p
 


int res[1010][1010] = {0};
int C(int n,int m,int p){
	if(m==0||m==n) return 1;
	if(res[n][m] != 0) return res[n][m];
	return res[n][m] = C(n-1,m)+C(n-1,m-1)%p;
} 

//把整张表都计算出来的递推代码
const int n = 60;
void calC(){
	for(int i = 0;i<=n;i++){
		res[i][0] = res[i][i] = 1;
	}
	for(int i = 2;i<=n;i++){
		for(int j = 0;j<=i/2;j++){
			res[i][j] = (res[i-1][j]+res[i-1][j-1])%p;//递推计算c(i,j)
			res[i][j-1] = res[i][j];//C(i,i-j) = C(i,j) 
		}
	}
} 

6

6.1vector常见用法

#include<vector>
#include<cstdio>
using namespace std;
//vector<typename> name; 
//vector<typename> Arrayname[arraySize];

//迭代器(iterator)可以理解成类似指针的东西.其定义是
//vector<typename>::iterator it; 

void solve(){
	vector<int> vi;
	for(int i = 1;i<=5;i++){
		vi.push_back(i);
	}
	//vi.begin();为取vi的首元素地址 
	vector<int>::iterator it = vi.begin();
	for(int i = 0;i<5;i++){
		printf("%d ",*(it+i));
	} 
} 
//从这里可以看出来vi[i]和*(vi.begin()+i)是等价的

//另一种遍历方法 

void solve1(){
	vector<int> vi;
	for(int i = 1;i<=5;i++){
		vi.push_back(i);//在vector后面添加一个元素.
		//vi.pop_back()可以删除vi末尾的元素.
		//size()用来获得vector中元素的个数.返回的是无符号类型的.但是可以用%d输出
		//clear()用来清空vector数组中所有元素.
		//insert(it,x)用来向vector的任意迭代器it处插入一个元素x.
		//例子:vi.insert(vi.begin()+2,-1)将-1插入到2的位置.
		//erase():删除单个元素,删除一个区间的元素.
		//erase(it)/erase(first,last); 
	}
	//迭代器支持自加自减操作. 
	for(vector<int>::iterator it = vi.begin();it != vi.end();it++){
		printf("%d ",*it);
	} 
} 

int main(){
	solve(); 
	printf("类似下标和指针的输出\n");
	solve1();
	printf("展现it可以自增\n"); 
	return 0;
}

6.2set常见用法

#include<cstdio>
#include<set> //内部有序,不含重复的容器. 
using namespace std;

void solve(){
	set<int>st1;
	st1.insert(100); 
	st1.insert(200);
	st1.insert(100);
	st1.insert(300);
	st1.insert(400);
	
	st1.erase(st1.find(100));//1 st.erase(it)
	st1.erase(400);//2 st.erase(value);
	
	//set<int>::iterator it = st.find(30);
	//st.erase(it,st.end());//删除30到结尾之间的元素 
	
	//size()获得set内元素个数
	//clear()清空set中的所有元素. 
	for(set<int>::iterator it1 = st1.begin();it1 != st1.end();it1++){
		printf("%d\n",*it1);
	} 
}

int main(){
	set<int>st;
	for(int i = 1;i<=3;i++){
		st.insert(i);//可以将i插入到set容器中. 
	}
	//set只能通过迭代器访问.*it就是set中的值了 
	set<int>::iterator it = st.find(2); //find(value)可以返回对应值为value的迭代器. 
	printf("%d\n",*it); 
	//以上两句也可以写成,,但是dev上跑不起来 
	//printf(%d\n",*(st.find(2));
	solve();
	return 0; 
}

6.3string常见用法

#include<stdio.h>
#include<iostream> 
#include<string>
using namespace std; 
//读入和读出.

void solve(){
	//length()和size,获得存放的字符数 
	//insert(pos,string)在pos号位置插入字符串string
	//insert(it,it2,it3)在原字符串的it位置开始插入,it2和it3是首尾迭代器. 
	
	//erase(it)删除单个元素.
	//erase(first,last)删除区间.
	//erase(pos,length)从pos开始删除length个元素.
	//clear()用以清空string 中的数据.
	
	//substr(pos,len) 返回 从pos位置开始,长度为len的子串.
	
	//string::npos 是一个常数.其本身的值为-1 unsigned_int类型.
	//是find 函数失配时候的返回值.
	
	//find(str2) 当str2是str1的子串的时候返回其在str1中第一次出现的位置.
	//find(str2,pos)从str1的pos位置开始查找与上面相同.
	//str1.find(str2,7) 
	 
	//replace(pos,len,str2)  从pos位置开始长度为len的子串替换为str2.
	//replace(it1,it2,str2)  把str2迭代器[it1,it2)范围的子串替换成为str2. 
	 
	
	//两个string可以通过=..来比较大小. 
}
 

int main(){
	string str = "abcd";
	for(int i = 0;i<str.length();i++){
		printf("%c",str[i]);
	}
	printf("\n"); 
	//如果要读入和输入整个字符串则只能用cin,cout
	 
	string s;
	cin>>s;
	cout<<s;
	//可以用c_str将string 转换成字符数组就可以用printf输出了
	printf("%s字符数组的输出\n",str.c_str());
	//insert函数和erase函数要用迭代器访问So  string迭代器不用写类型了. 
	for(string::iterator it = str.begin();it!=str.end();it++){
		printf("%c迭代器访问",*it); 
	}
	//字符串加法 
	string str3;
	str3 = str+s;
	str += s; //把s接上去str
	cout<<"\n字符串加法\n"<<str3<<endl;
	cout<<str <<endl; 
	
	solve();
	
	return 0;
}

6.4map常用用法

//map翻译为映射.map可以将任何基本类型.映射到基本类型包括 STL容器

//map<typename1,typename2> mp; 

//映射前类型key  (键)   映射后类型value (值)
//map会以键从小到大排序. 
//map可以通过下标和迭代器来访问.
#include<cstdio>
#include<map>
using namespace std;

int main(){
	map<char,int> mp;
	mp['m'] = 20;
	mp['r'] = 30;
	mp['a'] = 40;
	//迭代器访问 --失败 
//	map<char,int>::iterator it = mp.begin(); //不定义在for外面就报错.难搞啊. 
//	for(it = mp.begin();it != mp.end();it++);
//	{
//		printf("%c %d\n",it->first,it->second);
//	}
	//下标访问
	printf("下标访问:%d\n",mp['r']); 
	
//	find 返回关键值为key的映射迭代器 
	map<char,int>::iterator it = mp.find('m');
	printf("find返回关键字:%c %d\n",it->first,it->second); 
	
	//erase(it) 删除单个
	//erase(key) 删除的映射的键.
	//erase(first,last)   
	//size   clear 
	
	return 0;
} 

6.5queue常见用法

#include<stdio.h>
#include<queue>
using namespace std;
int main(){
	queue<int>q;
	if(q.empty()==true){
		printf("Empty\n");
	}else{
		printf("Not Empty%d\n",q.size());
	} 
	
	for(int i = 1;i<=5;i++){
		q.push(i);//
	}
	for(int i = 1;i<=3;i++){
		q.pop();//首元素出队 空参哦 
	}
	if(q.empty()==true){
		printf("Empty\n");
	}else{
		printf("Not Empty : %d\n",q.size());
	} 	

//	使用front和pop前必须判断是不是为空 
	printf("%d\n",q.front());
	printf("%d\n",q.back()); 
	return 0;
} 

6.6 priority_queue常见用法

//priority_queue 没有front()和back() 只能通过top来访问队首部元素.

//基本数据类型优先级设置 
//priority_queue <int,vector<int>,less<int> > q; 表示数字越大优先级越大.greater<int>表示数字越小优先级越大. 

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

//结构体的优先级设置 
struct fruit{
	string name;
	int price;
	//重载小于号运算符. 
	friend bool operator<(fruit f1,fruit f2){
		return f1.price > f2.price;//价格低的优先. 但是在sort排序cmp中却正好相反. 
	}
}f1,f2,f3;//创造对象.(错) 

struct cmp{//挺奇特 
	bool operator() (fruit f1,fruit f2){
		return f1.price> f2.price;
	}
}; 
		 
	

int main(){
	priority_queue<int,vector<int>,greater<int> >q;
	q.push(3);
	q.push(4);
	q.push(1);
	//使用top前必须使用empty判断队列是否为空
	 
	printf("%d\n",q.top());
	
//结构体的优先级设置 
	priority_queue<fruit> p;
	f1.name = "桃子";
	f1.price = 3;
	f2.name = "梨子";
	f2.price =  4;
	f3.name = "苹果";
	f3.price = 1;
	p.push(f1);
	p.push(f2);
	p.push(f3);
	cout<<p.top().name<<" "<<p.top().price<<endl; 
	
	//cmp类型的排序 
	priority_queue<fruit,vector<fruit>,cmp> k; 
	f1.name = "桃子";
	f1.price = 3;
	f2.name = "梨子";
	f2.price =  4;
	f3.name = "苹果";
	f3.price = 1;
	k.push(f1);
	k.push(f2);
	k.push(f3);
	cout<<k.top().name<<" "<<k.top().price<<endl; 
	return 0;
} 

6.8 pair常见用法

// pair 可以将两个元素绑在一起作为一个合成元素.类似下面的东西
/*struct{
	typeName1 first;
	typeName2 second;
}; */
//可以比较大小,先比first first相等再比second;

//常见用途
1.可以代替二元结构体的和其构造函数 
2.作为map的键值进行插入.
	mp.insert(make_pair("嘿嘿",5")); 
	mp.insert(pair<string,int >("heihei",555)); 
#include<iostream>
#include<utility>//可以偷懒用map代替
#include<string>
using namespace std;

int main(){
	pair<string ,int> p;
	p.first = "haha";
	p.second = 5;
	cout<<p.first<<" "<<p.second<<endl;

	//临时构造一个pair
	p = make_pair("xixi",55);
	cout<<p.first<<" "<<p.second<<endl;
	p = pair<string,int >("heihei",555); 
	cout<<p.first<<" "<<p.second<<endl;
	return 0;
} 

6.9 algorithm常见用法

//max(),min(),abs()参数必须是两个.可以是浮点数.
//但是abs()必须是整数.浮点数绝对值需要用math下的fabs 
//swap(),reverse(it,it2), 可以将数组指针[it,it2)之
//间的元素或者容器的迭代器在[it,it2)范围内进行反转 
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
 
using namespace std;

bool cmp(int a,int b){
	return a>b;
} 

int main(){
	int a[10] = {1,2,3,4};
	//a[0]~a[2]之间的序列需要求解next_permutation
	do{ 
		printf("%d%d%d%d\n",a[0],a[1],a[2],a[3]);
	} while(next_permutation(a,a+4));//有几个数要全排列就加几...尾元素的下一个地址. 
	
	
	fill(a,a+4,233 );
	for(int i = 0;i<4;i++){
		printf("%d ",a[i]);
	} 
	
	//容器的排序 
	vector<int> vi;
	vi.push_back(3);
	vi.push_back(1);
	vi.push_back(2);
	sort(vi.begin(),vi.end(),cmp);
	int i = 0;
	for(i;i<3;i++){
		printf("%d ",vi[i]);
	}
	
//	比较函数cmp  这个是配合着sort函数使用的作为sort函数的第三了参数来左右排序的规则.
bool cmp(string str1,string str2)
{
	return str1.length() < str2.length();//按照字符串长度有小到大. 大于号就是由大到小.记不住就都试试. 
}

	
	
	/* 
	lower_bound(first,last,val)//在范围内寻找第一个值大于等于val的元素的位置.是数组就返回该位置的指针,容器就返回迭代器
	upper_bound(first,last,val)//大于val的值. 
	 */ 
	return 0;
} 

7.3.3链表的基本操作

#include<stdio.h>
#include<stdlib.h>

struct node {
	int data;
	node *next;
}; 

//创建链表
node *create(int Array[])
{
	node *p, *pre, *head;  //pre保存当前结点的前驱 ,head 为头结点
	head = new node;  //创建头结点
	head -> next = NULL; //头结点不需要数据域。指针域初始化为NULL
	pre = head;//记录pre为head
	for(int i = 0; i < 5; i ++)
	{
		p = new node;
		p -> data = Array[i];
		p -> next = NULL;
		pre -> next = p;
		pre = p; 
	}
	
	return head; 
}
int main()
{
	int Array[] = {5 , 3, 6, 1, 2};
	node *L = create(Array); //创建链表,返回的头指针head赋值给L
	node *k = L -> next;
	while(k != NULL)
	{
		printf("%d", k ->data);
		k = k->next;
	}
	return 0; 
}

8.1深度优先搜索

/*
深度优先搜索是一种枚举所有完整路径以遍历所有情况的搜索方法. 

有n个物品.装进背包.背包容量V 物品的重量和价值为w[i] c[i] 怎样装可以令价值最大化 
输入:
5 8
3 5 1 2 2
4 5 2 1 3 
*/ 
#include<cstdio>
const int maxn = 30;
int n, V, maxValue = 0; //物品数量,背包容量,最大价值
int w[maxn], c[maxn];  //每个重量和价值
//index 为当前处理物品的编号
//sumW和sunC分别为总重量和总价值
void DFS1(int index, int sumW, int sumC)
{
	if(index == n)// 完成已经对n件物品的选择(死胡同) 
	{
		if(sumW <= V && sumC > maxValue)
			maxValue = sumC;
		return;
	}
	
	//岔道口
	DFS1(index + 1,sumW, sumC);  //不选第index件物品
	DFS1(index + 1, sumW + w[index], sumC + c[index]);//选第index件物品 
}
//时间复杂度为O(2^n) 可以优化
//剪枝优化
void DFS(int index, int sumW, int sumC)
{
	if(index == n)// 完成已经对n件物品的选择(死胡同) 
		return;
	DFS(index + 1,sumW, sumC);  //不选第index件物品
	
	//岔道口
	//只有加入第index件物品后为超过容量V,才能继续
	if(sumW + w[index] <= V)
		if(sumC + c[index] > maxValue)
			maxValue = sumC + c[index];
	DFS(index + 1, sumW + w[index], sumC + c[index]);//选第index件物品 
}
 


int main()
{
	scanf("%d%d", &n, &V);
	for(int i = 0;i < n; i++)
		scanf("%d", &w[i]);	//每件物品的重量
	for(int i = 0; i < n;i ++)
		scanf("%d", &c[i]);	//每件物品的价值
	DFS1( 0, 0, 0);	//初始时第 0 件物品,当总重量和总价值均为0
	printf("%d\n", maxValue);
	return 0; 
}

8.2广度优先搜索

//广度优先搜索.把每个分叉的第一个点先遍历然后每次深入一个点从左到右增加.
/*需要辅助队列. 
迷宫问题. 走到终点需要的最小步数量. 
 
5 5
.....
.*.*.
.*S*.
.***.
...T* 
2 2 4 3

没有成功 每次都返回负一 
*/ 

#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;
const int maxn = 100;
struct node {
	int x, y;	//location
	int step;	// min  step
}S, T, Node; 	//s为起点,T为终点,Node为临时结点. 

int n, m;	//n 为行 ,m为列
char maze[maxn][maxn];	//迷宫信息
bool inq[maxn][maxn]; 	//记录位置(x,y)是否进入过队
int X[4] = {0, 0, 1, -1};	//增量数组 
int Y[4] = {1, -1, 0, 0}; 

//检测位置(x,y)是否有效
bool test(int x,int y){
	if(x >= n || x < 0 || y >= m || y < 0) return false;	//超越边界
	if(maze[x][y] == '*') return false;		//墙壁
	if(inq[x][y] = true) return false;		//已经入队过
	return true; 
} 

int BFS() 
{
	queue<node> q;
	q.push(S);
	while(!q.empty())
	{
		node top = q.front();
		q.pop();
		if(top.x == T.x && top.y == T.y)
			return top.step;//终点直接返回最少步数 
		for(int i = 0;i < 4;i ++)
		{
			int newX = top.x + X[i];
			int newY = top.y + Y[i];
			if(test(newX,newY))
			{
				Node.x = newX,Node.y = newY;
				Node.step = top.step + 1;
				q.push(Node);
				inq[newX][newY] = true;
			}
		 
		}
	}
	return -1;//无法到达终点T是返回-1 
}

int main()
{
	scanf("%d%d", &n, &m);
	for(int i = 0;i < n;i++)
	{
		getchar();//
		for(int j = 0;j < m;j ++)
			maze[i][j] = getchar();
		maze[i][m + 1] = '\0';
	}
	scanf("%d%d%d%d", &S.x, &S.y, &T.x, &T.y);
	S.step = 0;
	printf("%d\n",BFS());
	return 0;
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值