FaFu--练习复盘

1、输出图形及二维数组应用

1.1.输出图形

描述

        编写程序打印n行如下图形,其中1≤n≤500。

输入用例   

        7                           

输出用例 

具体实现

#include"stdio.h"
int main(){
 int n,i,j;
   scanf("%d",&n);
   for(i = 1; i<= n; i++){
     for (j = 1; j<= n-i; j++)
         printf(" ");
     for(j =1 ;j<=i; j++)
           printf("%c",'A'+(n-j)%26);
     for(j =1 ;j<=i-1; j++)
           printf("%c",'A'+(n+j-i)%26);
        printf("\n");
    }
  return 0;
}

  

1.2.旋转数字

描述

        编写程序打印n行如下菱形图形(1≤n≤99),图形有n行n列个整数,图形从第1行的中间开始,数字分别是1,2,……n*n-1,n*n,并且顺时针向中间转入,如果1个数据项宽度不足n*n位,用0补足到n*n位。

 输入用例

        7

输出用例

       

具体实现

#include "stdio.h"
const int N0 = 100;
struct Dir{
 	int row,col;
	}dir[4] = {{1,1},{1,-1},{-1,-1},{-1,1}};
 int a[2*N0][2*N0] = {0};
 int main(){
  int n,i,j,m;
   scanf("%d",&n);
   int row,col,rowTest,colTest,d=0;
   row = 1;
   col = n;
   m = 0;
   i = n*n;
   while(i){
     i/=10;
       m++;
    }
   for(i = 1; i<= n*n; i++){
     a[row][col] = i;
       rowTest = row + dir[d].row;
       colTest = col + dir[d].col;
       if(rowTest < 1 || rowTest >= 2*n || colTest < 1 || colTest >= 2*n || a[rowTest][colTest] != 0){
         d = (d+1)%4;
           rowTest = row + dir[d].row;
           colTest = col + dir[d].col;
        }
       row = rowTest;
       col = colTest;
    }
   for( i = 1; i < 2*n ; i++){
     for (j = 1; j< 2*n; j++)
          if(i<=n && j<n+i || i>n && j<3*n-i)
          {
              if(a[i][j] == 0)
                printf("%*c",m,' ');
              else
                printf("%0*d",m,a[i][j]);
          }
          printf("\n");        
    }
  return 0;
}

1.3求和

描述

        有1个n×n的矩阵,从左上到右下称为主斜线(倾角135º),从右上到左下称为次斜线(倾角45º),在主斜线上最大,次斜线上最小的元素称为该矩阵的斜线鞍点,求出该矩阵所有斜线鞍点的和。

        如5×5的矩阵:元素7为上面矩阵的一个斜线鞍点,元素10和19也是上面矩阵的斜线鞍点。

输入用例

5

3        2        5        98        10

44     12        1       12         8 

67     61        45      7         19 

12     21        33      56        3

35     36        78      98        19    

输出用例

36

具体实现

#include "stdio.h"
const int N0 = 105;
int a[N0][N0];
int n;
void readData(){
 int i,j;
   scanf("%d",&n);
   for(i =1 ; i<=n ; i++)
      for(j=1; j<=n; j++)
        scanf("%d",&a[i][j]);
}
bool masterMax(int i, int j){
 int p,q;
   for(p=1; p<=n ; p++)
      for(q=1; q<=n; q++)
         if(p-q == i-j && a[p][q] > a[i][j])
               return false;
   return true;
}
bool slaverMin(int i,int j){
 int p,q;
   for(p=1; p<=n ; p++)
      for(q=1; q<=n; q++)
         if(p+q == i+j && a[p][q] < a[i][j])
               return false;
   return true;
}
int main(){
 int i,j,total;
   readData();
   for(total = 0, i=1; i<=n; i++)
       for(j=1; j<=n; j++)
           if(masterMax(i,j) && slaverMin(i,j))
               total += a[i][j];
  printf("%d\n",total);
   return 0;
}

2、数组与结构体应用

 2.1.数组中的元素查找

描述

        一维数组a中有20个整数,编写程序在数组a中查找元素q,如果找到第一个等于q的元素,则输出该元素在数组中的下标;如果没找到则输出-1。

输入用例

5

3 21 5 98 44 12 64 7 66 96 76 67 61 2 13 16 9 78 56 69

输出用例

2

具体实现

#include <stdio.h>
#include<math.h>
int main (){
    int a[20];
    int i,q,flag=0;
    scanf("%d",&q);
    for (i=0;i<20;i++) 
        scanf("%d",&a[i]);
    for(i=0;i<20;i++)
    	if (a[i]==q){
    		break;
    	}	
    if (i<20) 
        printf("%d",i);
    else 
        printf("-1");
    return 0;
 } 

2.2.多重元素下标查找

描述

        一维数组a中有10个整数,编写程序在数组a中查找所有值等于q的元素,并输出这些元素在数组中的下标;如果没找到则输出-1。

输入用例

58

57 89 76 35 58 65 58 73 58 47

输出用例

4 6 8 

具体实现 

#include <stdio.h>
#include<math.h>
int main (){
    int a[10];
    int i,q,flag=0;
    scanf("%d",&q);
    for (i=0;i<10;i++) scanf("%d",&a[i]);
    for(i=0;i<10;i++)
    	if (a[i]==q){
    		printf("%d ",i);
    		flag++;
		}	
	if (flag) ;//这有一个空语句
	else 
        printf("-1");
	return 0;
 } 

2.3.极端偏差成绩查找

描述

        输入某班级n(0<n<100)个学生的成绩到数组a中,找出所有成绩中与平均值绝对偏差最大的学生成绩,并输出该学生的成绩。

输入用例

10

23 21 5 17 19 42 6 10 8 31

输出用例

42

#include <stdio.h>
#include<math.h>
int main ()
{
    int a[100];
    int i,n,c,k,sum=0,avg;
    scanf("%d",&n);
    for (i=0;i<n;i++) scanf("%d",&a[i]);
    for (i=0;i<n;i++) sum=sum+a[i];
    avg=sum/n;
    c=fabs(a[0]-avg);
    k=0;
    for (i=0;i<n;i++)
	if (fabs(a[i]-avg)>c){
		c=fabs(a[i]-avg);
		k=i;
	}
	printf("%d",a[k]);
	return 0;
 } 

2.4.学生成绩标准差计算 

描述

        输入某班级n(0<n<100)个学生的成绩到数组a中,编写程序求成绩的标准差,求标准差的公式如下:

        其中,表示学生的总平均成绩,表示第i个学生的成绩。 

输入用例

6

95 85 75 65 55 45

输出用例

18.708

具体实现

#include <stdio.h>
#include<math.h>
int main (){
    int a[100];
    int i,n,c,k;
    double st,sum=0,avg;
    scanf("%d",&n);
    for (i=0;i<n;i++) 
      scanf("%d",&a[i]);
    for (i=0;i<n;i++) 
      sum=sum+a[i];
    avg=sum/n;
    sum=0;
    for (i=0;i<n;i++){
    	sum=sum+(a[i]-avg)*(a[i]-avg);
    }
	st=sqrt(sum/(n-1));
	printf("%.3lf",st);
	return 0;
 } 

2.5.次对角线元素求和

描述

        有一个5×5矩阵(即二维数组b),编写程序输出该矩阵次对角线上的所有元素之和。

输入用例

3          21        5        98        10

44        12        1        12        8

67        61        45      67        17

12        21        33      56        34

35        36        78      90        19

输出用例

123

具体实现

#include <stdio.h>
#include<math.h>
    int main (){
    int b[5][5];
    int i,j;
    long sum;
    for (i=0;i<5;i++)
    	for(j=0;j<5;j++)
    		scanf("%d",&b[i][j]);
    sum=0;
    for(i=0,j=5;i<5;i++){
    	j--;
		sum=sum+b[i][j];
    }
    printf("%ld",sum);
    return 0;
 } 

2.6.矩阵对角线区域调整

描述

        有一个5×5矩阵(即二维数组b),编写程序将矩阵的左下三角(含主对角线)各元素加10,右上三角各元素(不含主对角线)减10。

输入用例

13 21 55 98 47

12 18 19 67 61

89 80 36 78 10

89 87 67 80 12

12 33 88 57 70

输出用例 

23 11 45 88 37

22 28 9  57 51

99 90 46 68 0

99 97 77 90 2

22 43 98 67 80 

具体实现 

#include <stdio.h>
#include<math.h>
int main (){
  int b[5][5];
  int i,j;
	for(i=0;i<5;i++){
    	for(j=0;j<5;j++){
        scanf("%d",&b[i][j]);
        if(i<j){
        	b[i][j]-=10;
        	}else{
        	b[i][j]+=10;
        	}
          printf("%d ",b[i][j]);
        }
  	printf("\n");
    }
	return 0;
 } 

2.7.二维数组先列后行降序排序

 描述

        有一个n行m列(0<n<20,0<m<20)的整型二维数组b,编写程序对二维数组b[n][m]先按列降序排序,再按行降序排序。

输入用例

4 5

21  3   5   98   10

44 12  1   12    8

67 61 45  67   17

35 36 78  90    19

输出用例

98  78  67 61  19

90  45  44  36  17

67  35  12  10  5

21  12   8    3   1

具体实现 

#include <stdio.h>
int main (){
    int b[20][20];
    int n,m,i,j,k,temp;
     scanf("%d%d",&n,&m); 
    for (i=0;i<n;i++)
    	for(j=0;j<m;j++)
    		scanf("%d",&b[i][j]);
    for(k=0;k<m;k++)
      for(i=n-1;i>0;i--)
        for(j=0;j<i;j++)
          if(b[j][k]<b[j+1][k]){
          	temp=b[j][k];
            b[j][k]=b[j+1][k];
            b[j+1][k]=temp;
          }
      for(k=0;k<n;k++)
        for(i=m-1;i>0;i--)
          for(j=0;j<i;j++)
            if(b[k][j]<b[k][j+1]){
            	temp=b[k][j];
              	b[k][j]=b[k][j+1];
              b[k][j+1]=temp;
            }
    for (i=0;i<n;i++){
    	for(j=0;j<m;j++)
    		printf("%d ",b[i][j]);
    	printf("\n");
    	}
     return 0;
 } 

2.8. 二维数组字符串升序排序

描述

        输入n个字符串(长度小于20)存入二维数组c中,编写程序对其进行排序(由小到大)并按次序输出。

输入用例

3

bcd

abd

abc

输出用例

abc

abd

bcd

具体实现

#include<stdio.h>
#include<string.h>
void myGets(char s[]){
	char ch;
    while((ch=getchar())!='\n' && ch!=EOF)
      *s++=ch;
  	*s=0;
}
int main(){
	char c[20][20],temp[20];
  	int n,i,j;
  	scanf("%d",&n);
  	getchar();
  	for(i=0;i<n;i++)
    	gets(c[i]);
  	for(i=n-1;i>0;i--)
  		for(j=0;j<i;j++)
    		if(strcmp(c[j],c[j+1])>0){
          		strcpy(temp,c[j]);
          		strcpy(c[j],c[j+1]);
          		strcpy(c[j+1],temp);
        		}
   	for(i=0;i<n;i++)
        puts(c[i]);
    return 0;  
}

2.9.删除小写字符形成新字符串

描述

        从键盘输入一个字符串s,删除其中所有的小写字符后形成一个新字符串,然后输出。

输入用例

www.163.com

输出用例

.163.

具体实现

#include <stdio.h>
#include <string.h>
int main (){
    char s[30];
    int i,j;
    gets(s);
    i=0;
    while (s[i]!='\0'){
    	if(s[i]>='a' && s[i]<='z'){
    		j=i;
    		while (s[j]!='\0'){
    			s[j]=s[j+1];
    			j++;	
    		}
    		s[j-1]='\0';
    	}
    	else i++;
    }
    puts(s);	
    return 0;
 } 

2.10.恺撒密码加密 

描述

        朱迪斯·恺撒在其政府的秘密通信中使用恺撒密码进行信息加密,恺撒加密因而得其名。凯撒密码的基本思想是将待加密的信息(称为明文)中每个字母在字母表中向后移动常量key,得到加密信息(称为密文)。例如,假设字母表为小写英文字母表,key等于3,则对于明文computer systems将加密为frpsxwhu vbvwhpv。

输入用例

3

computer system

输出用例

frpsxwhu vbvwhpv

具体实现

#include <stdio.h>
#include <string.h>
int main (){
    char s[100]={0};
    int i,key;
    scanf("%d",&key);
    while(getchar()!='\n');
    gets(s); 
    i=0;
    while (s[i]!='\0'){
    	if ((s[i]>=65 && s[i]<=90)  ){
    	s[i]=(s[i]+key-65)%26+65;
    	}
    	if (s[i]>=97 && s[i]<=122){
    	s[i]=(s[i]+key-97)%26+97;	
    	}
    	i++;
    }
    puts(s);	
    return 0;
 } 

2.11.优秀学生信息输出

描述

        有n个学生,每个学生的数据包括学号、姓名和成绩,要求输出成绩优秀(大于等于90分)学生的信息(包括学号、姓名和整型成绩)。如果没有符合条件的,则输出“No”。

输入用例

3

1001 Make 86

1002 Linda 58

1003 Jone 90

输出用例

1003 Jone 90

具体实现 

#include <stdio.h>
#include <string.h>
int main (){
    struct student{
    	int num;
    	char name[10];
    	int score;	
    };
    struct student stu[20];
    int n,i,flag=0;
    scanf("%d",&n);
    for (i=0;i<n;i++){
    	scanf("%d%s",&stu[i].num,stu[i].name);
    	scanf("%d",&stu[i].score);
    } 
    for (i=0;i<n;i++)
    	if (stu[i].score>=90){
    		flag=1;
    		printf("%d %s %d\n",stu[i].num,stu[i].name,stu[i].score);
    	}
    	if(flag==0) 
            printf("No");
    return 0;
 } 

2.12.高分学生筛选输出

描述

        有n个学生,每个学生的数据包括学号、姓名和3门课程的成绩,要求输出平均成绩高于90分以上(包括90分)或全部课程成绩均在85分以上(包括85分)的学生信息(包括学号和姓名),如果没有符合条件的,则输出“No”。

输入用例

3

1001 Make 86 91 89

1002 Linda 78 78 80

1003 Jone 90  67 71

输出用例

1001 Make

具体实现

#include <stdio.h>
#include <string.h>
int main (){
    struct student{
    	int num;
    	char name[10];
    	int score[3];
    	float avg;
    };
    struct student stu[20];
    int n,i,sum,flag=0;
    scanf("%d",&n);
    for (i=0;i<n;i++){
    	scanf("%d%s",&stu[i].num,stu[i].name);
    	scanf("%d%d%d",&stu[i].score[0],&stu[i].score[1],&stu[i].score[2]);
    } 
    for (i=0;i<n;i++){
    	stu[i].avg=(stu[i].score[0]+stu[i].score[1]+stu[i].score[2])/3.0;
    	if ((stu[i].avg>=90)||(stu[i].score[0]>=85 && stu[i].score[1]>=85 && stu[i].score[2]>=85)){
    		flag=1;
    		printf("%d %s\n",stu[i].num,stu[i].name);
    	}
    }
    if(flag==0) printf("No");
    return 0;
 } 

 3、函数练习

3.1、函数表达式(1)

描述

        根据以下公式计算数学表达式的值,并将结果作为函数值返回。在main()函数中输入x,调用函数fun(x),并输出fun(x)的值。

1.png

输入

        输入1行,包含1个double类型的浮点数,即输入的变量x。

输出

        输出1行,包含1个保留3位小数的double类型的浮点数,即输出的函数值。

输入样例 1                                                 输入样例 2 

0.26                                                                8.5

输出样例 1                                                输出样例 2

0.265                                   1.904

具体实现

#include <stdio.h>
#include<math.h>
double fun(double x) {
	double y;
	if (x>=0)
		y=(3*x*sin(x)+tan(x) )/(1.5+x);
	else
		y=(3*x*sin(x)+tan(x) )/(1.5-x);
	return y;
}

int main (){
double x;
scanf("%lf",&x);
printf("%.3lf",fun(x));
return 0;
}

3.2、 函数表达式(2)

描述

        根据以下公式计算数学表达式的值,并将结果作为函数值返回。在main()函数中输入x,调用函数fun(x),并输出fun(x)的值。

2.png

输入

        输入1行,包含1个double类型的浮点数,即输入的变量x。

输出

        输出1行,包含1个保留3位小数的double类型的浮点数,即输出的函数值。

输入样例 1                                         输入样例 2 

0.26                                 18.5

输出样例 1                                        输出样例 2

0.607                                342.250

具体实现

#include <stdio.h>
#include<math.h>
double fun(double x) {
	double y;
	if (x<10)
		y=(sqrt(2.5+cos(x)))/(x*sin(x)+3);
	else
		y=x*x;
	return y;
}

int main (){
double x;
scanf("%lf",&x);
printf("%.3lf",fun(x));
return 0;
}

3.3、实现找素数函数

描述

        完成函数IsPrime(int x),该函数用于判断整数x是否为素数,并将判断结果作为函数值返回。在main()函数中输入2个正整数m和n分别作为区间的上、下界,调用函数IsPrime(x)求[m,n]区间内所有素数,并按从小到大的次序输出。

输入

        输入1行,包含2个整数,即正整数m和n,两个整数之间用空格隔开。

输出

        输出1行,包含多个整数,每个整数之间用空格隔开。

输入样例 1                                                输入样例 2 

2 15                                  10 30

输出样例 1                                                输出样例 2

2 3 5 7 11 13                        11 13 17 19 23 29

具体实现

#include <stdio.h>
#include<math.h>
int fun(int m,int n) {
	for (;m<=n;m++)
	{
		int i;
		for (i=2;i<m;i++) if (m%i==0) break;
		if (i==m) printf ("%d ",m);
	}
}

int main (){
	int m,n;
	scanf("%d%d",&m,&n);
	fun(m,n);
return 0;
}

3.4、可逆素数

描述

        完成函数IsPrime(int x)和函数Reverse(int x)。函数IsPrime(x)用于判断整数x是否为素数;函数Reverse(x)用于求整数x反序数(即将各位数字的顺序倒过来)。在main()函数中输入2个正整数m和n分别作为区间的上、下界,调用函数IsPrime(x)和函数Reverse(x)求[m, n]区间内所有可逆素数(即一个素数的反序数也是素数),并按从小到大的次序输出。

输入

        输入1行,包含2个整数,即正整数m和n,两个整数之间用空格隔开。

输出

        输出1行,包含多个整数,每个整数之间用空格隔开。

输入样例 1 

10 50

输出样例 1

11 13 17 31 37

具体实现

#include <stdio.h>
#include<math.h>
int fun(int m,int n) {
	int i,j,k;
	int a,b,c,d;	
	for (;m<=n;m++){
		for (i=2;i<m;i++) if (m%i==0) break;
		if (i==m){
			a=m%10;
			b=m%100-a;
			c=(m-a-b)/100;
			if (m>100) d=a*100+b+c;
			else d=b/10+a*10;
			for (j=2;j<d;j++) if (d%j==0) break; 
			if (d==j) printf("%d ",m);
		}
	}
}

int main (){
int m,n; 
scanf("%d%d",&m,&n);
fun(m,n);
return 0;
}

3.5、 最大公约数

描述

        完成函数Gcd(int x, int y),该函数用于求整数x和y的最大公约数,并返回最大公约数。在main()函数中输入两个正整数a和b,调用函数Gcd求这两个整数的最大公约数,并输出求解结果。

输入

        输入1行,包含2个整数,即正整数a和b,整数之间用空格隔开。

输出

        输出1行,包含1个整数,即最大公约数。

输入样例 1 

15 25

输出样例 1

5

具体实现

#include <stdio.h>
#include<math.h>
int Gcd(int a,int b) {
	int rem;		
	while(b > 0){
		rem = a % b;
		a = b;
		b = rem;
	}
	return a;
}

int main (){
	int a,b;
	scanf("%d%d",&a,&b);
	printf("%d",Gcd(a,b));
return 0;
}

3.6、基于最大公约数的最小公倍数

描述

        完成函数Gcd(int x, int y),该函数用于求整数x和y的最大公约数,并返回最大公约数。在main()函数中三个正整数a、b和c,调用函数Gcd求这个三个整数的最大公约数和最小公倍数,并输出求解结果。

输入

        输入1行,包含3个整数,即正整数a、b和c,整数之间用空格隔开。

输出

        输出1行,包括2个整数,即最大公约数和最小公倍数。

输入样例 1 

2 4 6

输出样例 1

2 12

具体实现

#include <stdio.h>
int Gcd(int x,int y){	//用于求整数x和y的最大公约数
	int r;
	//**************************************
	if (x < y){ //swap(x, y)
		r = x; 
		x = y;
		y = r;
	}
	
	//递归法(辗转相除法)求最大公约数
	if(y==0){
		return x;
	}else{
		return Gcd(y, x%y);
	}
	
	//======================================
}

int main(){
	int a,b,c,t1,t2, t3, t4, t5;	//a,b,c-用于求最大公约数和最小公倍数的三个整数,
	
	scanf("%d%d%d",&a,&b,&c);	//输入(接收)待求最大公约数和最小公倍数的3个整数
	//**************************************
	t1 = Gcd(a, b);		//求整数a 和 b的最大公约数t1
	
	t2 = Gcd(t1, c);	//求整数t1 和 c的最大公约数t2 —— 三个数的最大公约数

	t3 = (a * b)/t1;	//求整数a 和 b的【最小公倍数】t3

	t4 = Gcd(t3, c);	//求整数t3 和 c的最大公约数t4

	t5 = (t3 * c)/t4;	//求整数t3 和 c的【最小公倍数】t5 —— 三个数的【最小公倍数】
	
	printf("%d %d\n", t2, t5);
	//======================================
	return 0;
}

=================================================================
#include <stdio.h>
int Gcd(int x,int y){
	while(y^=x^=y^=x%=y);
    return x;
}

int main(){
	int a,b,c,t1,t2;
	
	scanf("%d%d%d",&a,&b,&c);
	//**************************************
	t1 = Gcd(Gcd(a, b),c);
	t2 = (((a * b)/Gcd(a, b)) * c)/Gcd((a * b)/Gcd(a, b), c);	
	printf("%d %d\n", t1, t2);
	//======================================
	return 0;
}

3.7、 寻找最大平均偏差元素

描述

        完成函数find(int a[], int n),该函数用于找出数组a中与所有元素的平均值绝对偏差最大的元素,并返回该元素值。在main()函数中输入数组a各元素的值以及元素个数n,调用函数find求解与平均值绝对偏差最大的元素,并输出求解结果。

输入

        输入2行,第1行有1个整数,即元素个数n,第2行有n个整数,即数组a的元素值,整数之间用空格隔开。  

输出

        输出1行,包含1个整数,即与平均值绝对偏差最大的元素。

输入样例 1 

10
23 21 5 98 89 12 86 80 8 61

输出样例 1

98

具体实现

#include <stdio.h>
#include<math.h>
int find(int a[],int n) {
	int i,c,k,sum=0,avg=0;
	c=abs(a[0]-avg);
	k=0;
	for (i=0;i<n;i++)
		sum=sum+a[i];
		avg=sum/n;
	for (i=1;i<n;i++)
		if (fabs(a[i]-avg)>c){
			c=fabs(a[i]-avg);
			k=i;
		}
	return a[k];
}
int main (){
	int a[100];
	int i,n;
	scanf("%d",&n);
	for (i=0;i<n;i++)
		scanf("%d",&a[i]);
	printf("%d",find(a,n));
	return 0;
 }

3.8、 寻找最小平均偏差元素及其下标

描述

        完成函数find(int a[], int n),该函数用于找出数组a中与所有元素的平均值绝对偏差最小的元素,并返回该元素值以及该元素所在的下标。在main()函数中输入数组a各元素的值以及元素个数n,调用函数find求与平均值绝对偏差最小的元素及其下标,并输出求解结果。

输入

        输入有2行,第1行有1个整数,即元素个数n,第2行有n个整数,即数组a的元素值,整数之间用空格隔开。

输出

        输出有1行,包括2个整数,即与平均值绝对偏差最小的元素值和元素所在的下标。

输入样例 1 

10
23 21 5 98 89 12 86 80 8 61

输出样例 1

61 9

具体实现

#include <stdio.h>
#include <math.h>
struct eType{	
	int x;	
	int index;
};
eType find(int a[],int n){
	int k;	
	double avg=0.0, minDiff;
	for(int i=0; i<n; i++){
		avg += a[i];
	}
	if(n>0){
		avg /=n;
	}
	k=0;
	minDiff = fabs(a[0]-avg);
	for(int t=1; t<n; t++){
		if(fabs(a[t]-avg) < minDiff){
			k=t;
			minDiff = fabs(a[t]-avg);
		}
	}
	struct eType rs={a[k], k};
	return rs;	
}
int main(){
	int a[100];	
	int i,n;	
	eType f;
	scanf("%d",&n);			
	for (i=0;i<n;i++)
		scanf("%d",&a[i]);	
	f = find(a, n);		
	printf("%d %d\n", f.x, f.index);
	return 0;
}

3.9、 递归计算阶乘和

描述

        完成递归函数fact(int n),该函数用递归调用方法求n!的值,并返回该值。在main()函数中输入整数n,通过调用函数fact,求1!+2!+…+n!的值。

输入

        输入1行,包含1个整数,即输入的整数n。

输出

        输出1行,包含1个整数,即1!+2!+…+n!的值。

输入样例 1 

3

输出样例 1

9

具体实现

#include <stdio.h>
#include<math.h>
int sum(int n) {
	int f;
	if(n==1) 
      f=1;
	else  
      f=sum(n-1)*n;
	return f;
}
int main ()
{
	int i,n;
	long s=0;
	scanf("%d",&n);
	for (i=1;i<n+1;i++)
		s=s+sum(i);
	printf ("%d",s);
	return 0;
 }

3.10、递归计算累加数列和

描述

        完成递归函数fan(int a, int n),该函数递归调用方法求aa…a(n个a)的值。在main()函数中输入整数n,通过调用函数fan,求a+aa+aaa+aa…a(n个a)的值。2

输入

        输入1行,包含2个整数,即输入的整数a和n,整数之间用空格分隔。

输出

        输出1行,包含1个整数,a+aa+aaa+aa…a(n个a)的值。

输入样例 1 

2 3

输出样例 1

246

具体实现

#include <stdio.h>
#include<math.h>
int sum(int a,int n) {
	int i;
	long sn,sum=0;
 		sn=0;
	 for(i=1;i<=n;i++){
 		sn=a+sn*10;
 		sum=sum+sn;
	 }
	 return sum;
}
int main ()
{
	int a,n;
	scanf("%d%d",&a,&n);
	printf("%d",sum(a,n));
 }

3.11、宏实现的区间整除性检查

描述

        编写带参数的宏P,实现求2个整数相除的余数。在main()函数中输入2个正整数m和n分别作为区间的上、下界,利用宏P求[m,n]区间所有既被3整除也被7整除的数,并按从小到大的次序输出。

输入

        输入1行,包括2个整数,即正整数m和n,两个整数之间用空格隔开。

输出

        输出1行,包括多个整数,每个整数之间用空格隔开。

输入样例 1 

10 30

输出样例 1

21

具体实现

#include <stdio.h>
#define p(a,b) a%b
int main ()
{
	int m,n;
	scanf("%d%d",&m,&n);
	for (;m<=n;m++){
		if(p(m,3)==0 && p(m,7)==0)
			printf ("%d ",m);	
	}
 return 0;
 }

3.12、 三数最大值宏计算器

描述

        编写带参数的宏MAX,实现求两数中的较大值。在main()函数中输入3个整数x、y和z,利用宏MAX求这三个数的最大值。

输入

        输入1行,包括3个整数,即输入的整数x、y和z,整数之间用空格隔开。

输出

        输出1行,包括1个整数,即三个数的最大值。

输入样例 1 

100 800 300

输出样例 1

800

具体实现

#include <stdio.h>
#define MAX(a,b,c) c>(a>b?a:b)?c:(a>b?a:b)
int main ()
{
	int a,b,c;
	scanf("%d%d%d",&a,&b,&c);
	printf("%d",MAX(a,b,c));
 return 0;
 }

 4、指针的应用

4.1、三角形周长和面积计算程序

描述

        已知三角形的三条边的长度,求该三角形的周长和面积,如果三个边不能构成三角形,则三角形的周长和面积都为0。完成程序的编写。

输入

        输入1行,包含3个实数,各实数之间用空格隔开。

输出

        输出1行,包含2个实数(用一个空格隔开),分别是三角形的周长和面积,结果保留2位小数,第3位小数四舍五入。

输入样例 1                                                                 输出样例 1

5.968  5.123 7.63                              18.72 15.26

具体实现

#include<stdio.h>
#include<math.h>
void CalAreaAndPremiter(double a,double b,double c){
  double s=0,area=0,premiter=0;
  if(a+b>c&&a+c>b&&b+c>a){
		s=(a+b+c)/2;
		premiter=2*s;
		area=sqrt(s*(s-a)*(s-b)*(s-c));
		printf("%.2lf %.2lf",premiter,area);
	}else 
		printf("%.2lf %.2lf",premiter,area);
}
int main(){
	double a,b,c;
	scanf("%lf%lf%lf",&a,&b,&c);
	CalAreaAndPremiter(a,b,c);
	return 0;
}

4.2、三个实数排序程序

描述

        输入三个实数,从小到大输出该三个实数。完成程序的编写。

输入

        输入1行,包含3个实数,各实数之间用空格隔开。

输出

        输出1行,包含从小到大排列的3个实数,各实数之间用空格隔开。

输入样例 1                                                         输出样例 1

35.3  21.73  28.92                        21.73 28.92 35.30

具体实现

#include<stdio.h>
int main()
{	
	double a,b,c,d;
	scanf("%lf%lf%lf",&a,&b,&c);
	if(a>b)
	{
		d=a;a=b;b=d;     //a、b的值互换,互换后a≤b
	}
	if(a>c)
	{
		d=a;a=c;c=d;      //a、c的值互换,互换后a≤c
	}
	if(b>c)
	{
		d=b;b=c;c=d;      //b、c的值互换,互换后b≤c
	}
	printf("%5.2lf %5.2lf %5.2lf\n",a,b,c);
}

4.3、 指针排序程序

描述

        用指针的方法将n个整数存入a数组中,再用指针的方法将a数组中的数据从小到大排序输出。完成程序的编写。

输入

        输入2行,第1行是一个整数n;第2行有n个整数,整数之间用空格隔开。

输出

        输出1行,包含n个从小到大的整数,整数之间用1个空格隔开。

输入样例 1                                                         输出样例 1

10                                        5 6 8 10 12 19 21 23 61 98
23 21 5 98 19 12 6 10 8 61

具体实现

#include "stdio.h"
#define N0 100
void sortP(int a[], int n){	
	int *pi, *pj, t;
	for(pi=a; pi<a+n-1; pi++){
		for(pj=a; pj<a+n-1-(pi-a); pj++){
			if(*pj > *(pj+1)){
				t = *pj;
				*pj = *(pj+1);
				*(pj+1) = t;
			}
		}
	}
}
int main(){
	int a[N0], n, *p;	
	scanf("%d", &n);						
	for(p=a; p<a+n; p++){
		scanf("%d", p);
	}	
	sortP(a, n);
	for(p=a; p<a+n-1; p++)
		printf("%d ", *p);
	printf("%d\n", *p);
	return 0;
}

4.4、 指向指针的指针排序程序

描述

        用指向指针的指针方法将n个字符串存入a数组,再用指向指针的指针方法将n个字符串从小到大排序输出。完成程序的编写。

输入

        输入n+1行,第1行是一个整数n;第2行到第n+1行每行有一个字符串。

输出

        输出n行,每行包含1个字符串,n个字符串从小到大排序输出。

输入样例 1                                                         输出样例 1

5                                         237MJ BNVC
asdkf3&  2345aoqwer                       KJ657KHL
KJHKlkdfd                                 KJH386skdfl
237MJ  BNVC                               KJHKlkdfd
KJH386skdfl                               asdkf3& 2345aoqwer
KJ657KHL

具体实现

#include <stdio.h>
#include <string.h>
const int N0=100;
void sortStrings(char a[][N0+1], int n ){
	char *pa[N0], **pi, **pj, t[N0+1];
	for(int i=0; i<n; i++)
		pa[i]=a[i];
	for(pi=&pa[0]; pi<&pa[0]+n-1; pi++){
		for(pj=&pa[0]; pj<&pa[0]+n-1-(pi-&pa[0]); pj++){
			if(strcmp(*pj, *(pj+1))>0){	
				strcpy(t, *pj);
				strcpy(*pj, *(pj+1));
				strcpy(*(pj+1), t);
			}
		}
	}	

}
int main(){
	char a[N0][N0+1], *pa[N0], **p;
	int n, i;		
	scanf("%d ", &n);
	for(i=0; i<n; i++)
		pa[i]=a[i];	
	for(p=&pa[0]; p<&pa[0]+n; p++){
		gets(*p);
	}
	sortStrings(a, n);	
	for(p=&pa[0]; p<&pa[0]+n; p++){
		puts(*p);
	}
	return 0;
}

4.5、 查找最大整数程序

描述

        编写一个返回值为指针的函数,输出n个整数中的最大整数。完成程序的编写。

输入

        输入2行,第1行是一个整数n;第2行有n个整数,整数之间用空格隔开。

输出

        输出1行,包含1个整数,即n个数中最大的那个。

输入样例 1                                                         输出样例 1

10                                        98
23 21 5 98 19 12 6 10 8 61

具体实现

#include "stdio.h"
const int N0=100;
int *maxInt( int a[], int n ){
	int *p, *pm;
	pm=a;
	for(p=a+1; p<a+n; p++){
		if(*p > *pm){
			pm=p;
		}
	}
	return pm;	
}
int main(){
	int a[N0], n, *p;
	scanf("%d", &n);		
	for(p=a; p<a+n; p++)
		scanf("%d", p);
	p=maxInt( a, n );
	printf("%d\n", *p );
	return 0;
}

4.6、学生成绩排序程序

描述

        某班级有n个学生,每个学生都有3门课的成绩:语文、数学、英语。用指向结构体的指针将数据存入结构体数组,再编写一个返回值是指针的函数,输出总分最高的学生的学号和总分,如果有最高相同的总分,输出语文成绩高的那位,如果语文成绩仍然相同,则输出学号小的那位。完成程序的编写。

输入

        输入n+1行:第1行为一个正整数n,表示该班级的学生人数。第2到n+1行,每行有3个用空格隔开的数字,第j行的3个数字依次表示学号为j-1的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为l~n(恰好是输入数据的行号减1)。

输出

        输出1行,每行有1个学号和1个总分,2个数据之间用空格隔开。

输入样例 1                                                 ​​​​​​​        输出样例 1

6                                         3 264
78 44 40
91 91 82
93 91 80
61 88 33
98 46 83
76 93 67

具体实现

#include "stdio.h"
const int N0=500;
struct node{
	int no; // 学号
	int c,m,e,total;
};

node *maxTotal(node a[], int n){
	node *pm, *p;
	pm = a;
	for(p=a+1; p<a+n; p++){	
		if(p->total > pm->total){
			pm = p;
		}else if(p->total == pm->total){
			if(p->c > pm->c){
				pm = p;
			}else if(p->c == pm->c){
				if(p->no < pm->no){
					pm = p;
				}
			}
		}
	}
	return pm;
}
int main(){
	node a[N0], *p;	
	int n, i;		
	scanf("%d", &n);
	for(p=a,i=1; p<a+n; p++,i++){
		scanf("%d%d%d", &p->c, &p->m, &p->e );
		p->total=p->c + p->m + p->e;		
		p->no=i;
    }								
	p=maxTotal( a, n );
	printf("%d %d\n", p->no, p->total);
	return 0;
}

4.7、 字符串中整数求和程序

描述

        将字符串中的正、负整数取出求和。如字符串“w&sk234 K3wzm3455kdf43dkf-56slk%9”中正、负整数取出的和=234+3+3455+43-56+9=3688,程序运行后输出3688。注意:

(1)需要考虑字符串中出现的正负号(+, -),即所有转换结果为正或负整数。

(2)空格为字符串的有效字符、不能忽略。例如,字符串"-□345.123"(□表示空格)应转换为-0,345,123三个整数,而不是-345和123两个整数!

(3)需要考虑'0'开始的数字字符串情况,比如"00035",应转换为整数35;"000"应转换为整数0;"00.0035"应转换为整数0和35(忽略小数点:mmm.nnn当成两个数mmm和nnn来识别)。

(4)不考虑转换后整数超出范围情况,即测试用例中可能出现的最大整数不会超过unsigned int可处理的范围;

(5)输入字符串不会超过100Bytes,请不用考虑超长字符串的情况。

完成程序的编写。

输入

        输入1行,一个字符串。

输出

        输出1个整数,是字符串中所有正、负整数的和。

输入样例 1                                                                 输出样例 1

w&sk234 K3wzm3455kdf43dkf-56slk%9              3688

具体实现

#include "stdio.h"
#include "string.h"
#include<iostream>
using namespace std;
int sumInt( char *s ){
	int sum=0, t=0, sign;	
	char *p=s;			
	bool inNumber=false;
	while(*p){
		if(!inNumber && *p>='0' && *p<='9'){
			inNumber = true;
			t = 0;
			if(p>s && *(p-1)=='-'){
				sign = -1;
			}else{
				sign = 1;
			}
		}
		if(inNumber && (*p < '0' ||  *p > '9')){
			inNumber = false;
			sum += t * sign;
		}
		if(inNumber){							   
			t = t*10 + (*p-'0');
		}
		
		p++;
	}
	if(inNumber){
		sum += t * sign;
	}
	return sum;
}

int main(){
	char s[1000+1];                  
	cin.getline(s,1001);                        
	printf("%d\n", sumInt(s));	
	return 0;
}

4.8、 大正整数相加程序

描述

        求2个大正整数之和。完成程序的编写。

输入

        输入2行,每行是1个大正整数。

输出

        输出1个整数,是上面2个大整数的和。

输入样例 1                                                                         输出样例 1

45656834234234095782376907905623                   45656834328124448764717457703658
         93890352982340549798035

具体实现

#include <stdio.h>
#include<malloc.h>
#include <string.h>
#define MAXLEN 500
char num1[MAXLEN];
char num2[MAXLEN];
int i, j, n, r;
int L1, L2, L;
char *sum;
void reverse(char *s)
{
	n = strlen(s);
	i = 0, j = n - 1;
	while(i < j)
	{
		char c = s[i];
		s[i] = s[j];
		s[j] = c;
		i++, j--;
	}
}
int main()
{
	r = n = 0;
	scanf("%s", num1);
	scanf("%s", num2);
	reverse(num1);
	reverse(num2);
	L1 = strlen(num1), L2 = strlen(num2);
	L = L1 > L2 ? L1 : L2;
	L += 2;
	sum = (char*)malloc(sizeof(char)*L);
	memset(sum, 0, L);
	L = L1 < L2 ? L1 : L2;
	for (i = 0; i < L; i++)
	{
		n = num1[i] - '0' + num2[i] - '0';
		sum[i] = (r + n) % 10 + '0';
		r = (r + n) / 10;
	}
	if (L1 <= L2)
	{
		while (i < L2)
		{
			n = num2[i] - '0';
			sum[i] = (r + n) % 10 + '0';
			r = (r + n) / 10;
			i++;
		}
	}
	else
	{
		while (i < L1)
		{
			n = num1[i] - '0';
			sum[i] = (r + n) % 10 + '0';
			r = (r + n) / 10;
			i++;
		}
	}
	if (r)
		sum[i] = r + '0';
	sum[i + 1] = 0;
	reverse(sum);
	printf("%s", sum);
	return 0;
}

4.9、 删除子字符串程序

描述

        在主字符串中删除所有子字符串。完成程序的编写。

输入

        输入2行,第1行是主字符串,第2行是子字符串。

输出

        输出1行,即删除所有子字符串后的主字符串。

输入样例                                                                                输出样例

hyuaaaabcad;dsj2390aaabcadldkaaaaabcaaabcade          hyua;dsj2390ldkaaaaabce
aaabcad

具体实现

#include<stdio.h>
#include<string.h>

const int N0=1000;

char *index(char s[],char *sub){
 int i =0,j=0;
  char *p=sub;
  if(*sub == '\0') 
    return NULL;
  char *pi=s,*pj=sub;
  while(*pi && *pj)
  	if(*pi == *pj){
    	pi++;
      	pj++;
    }else{
    	pi = pi-(pj-sub)+1;
      	pj=sub;
    }
    if(*pj =='\0')
      return pi-(pj-sub);
    else
      return NULL;
  }
int main(){
	char s[N0+1],sub[N0+1],*p,*q;
  int sublen;
  gets(s);
  gets(sub);
  sublen=strlen(sub);
  while(p=index(s,sub)){
  	q=p+sublen;
    while(*p++=*q++);
  }
  puts(s);
  return 0;
}

4.10、 字符串替换程序

描述

        输入3行字符串,分别是s字符串,t字符串和r字符串。如果s字符串中有包含t字符串,则用r字符串替换之。例如:s=“12aaabc3aaaaaabc#$%aaabc”,t=“aaabc”,r=“abc”,将s中的“aaabc”替换成“abc”之后,s=“12abc3aabc#$%abc”。输出替换之后的s字符串。完成程序的编写。

输入

        输入3行字符串,分别是s字符串,t字符串和r字符串。

输出

        输出将s字符串中包含的t字符串,用r字符串替换之,输出替换之后的s字符串。

输入样例 1                         ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        输出样例 1

ALKJFOE23DLS67AFAOE                       ALKJFXYZ23DLS67AFAXYZ
OE
XYZ

具体实现

#include<stdio.h>
#include<string.h>

const int N0=1000;

char *index(char s[],char *sub){
 int i =0,j=0;
  char *p=sub;
  if(*sub == '\0') 
    return NULL;
  char *pi=s,*pj=sub;
  while(*pi && *pj)
  	if(*pi == *pj){
    	pi++;
      	pj++;
    }else{
    	pi = pi-(pj-sub)+1;
      	pj=sub;
    }
    if(*pj =='\0')
      return pi-(pj-sub);
    else
      return NULL;
  }
void insStr(char *s,char *r ,char *p){
	char *pi,*pj;
  int i,j;
  int len=strlen(r);
  for(i=strlen(s);i>=p-s;i--)
    s[i+len]=s[i];
  for(i=p-s,j=0;r[j];i++,j++)
    s[i]=r[j];
}
int main(){

	char s[N0+1],t[N0+1],r[N0+1],*p,*p1,*q;
	  int tlen;
	  gets(s);
	  gets(t);
	  gets(r);
	  tlen=strlen(t);
	  while(p=p1=index(s,t)){
	  	q=p+tlen;
	    while(*p++=*q++);
	    insStr(s,r,p1);
  	}	
	  puts(s);
	  return 0;
	}

4.11、 有序表合并去重程序

描述

        有2个从小到大已经排序好的(有序)表,每个结点的数据是1个整数,已知两个表的数据存放在带头结点的单向链表中,将2个有序表合并成1个新的有序表,要求新的有序表中去掉重复相同的数据。完成程序的编写。

输入

        输入4行,第1行有1个整数n,即第1个表的结点数,第2行有n个整数;第3行有1个整数m,即第2个表的结点数,第4行有m个整数。整数之间用空格隔开。

输出

        输出1行,将上述2个表的数据从小到大排序输出,数据中没有相同项,每个整数之后输出1个空格。

输入样例 1                                                                 输出样例 1

6                                              -5 3 6 8 11 25 43 67 84 92 96 99 
3 6 11 25 67 84
10
-5 3 8 25 25 43 67 92 96 99

具体实现

#include "stdio.h"
const int INF=0x7fffffff; //无穷大整数
struct ND
{	int data; 
	struct ND *next; 
};

ND *createLink( ) 
{	ND *head, *p;
	int n; 
    head = p = new ND; 
	scanf("%d", &n);
	while( n-- )
	{	p->next = new ND; 
		p = p->next;  
		scanf("%d", &p->data); 
	}
	p->next = NULL; 
	return head;    
}
void printLink( ND *head ) 
{	ND *p=head->next;  
	if( p==NULL )return ;
	while( p )
	{	printf( "%d ",p->data );
		p=p->next;
	}
	printf("\n");
}

void deleteLink( ND *head) 
{	ND *p=head;
	while( p )
	{	head = p->next;
		delete p;
		p = head;
	}
}

ND * megerLink( ND *ha, ND *hb ) //合并2有序表,返回合并后链表头结点的地址
{	ND *pa=ha->next, *pb=hb->next, *hc, *pc;
	int data, lastData=INF; //lastData为上一个结点的数据项,用于判定是否有相同数据
	hc=pc=new ND;
//************************************************
	while(pa || pb){
		if(pa&&(pb==NULL || pa->data <= pb -> data)){
			data= pa->data;
			pa=pa->next; 
		}
		else{
			data =pb->data;
			pb = pb->next;
		}
		if(data != lastData){
			pc->next=new ND;
			pc=pc->next;
			pc->data=data;
			lastData=data;
		}
	} 
	pc->next=NULL;
	return hc;
//=================================================
	return hc;
}
int main()
{	ND *ha, *hb, *hc;
	//freopen( "sc6_6b.in", "r", stdin);
	//freopen( "sc6_6b.out", "w", stdout);
	ha = createLink();
	hb = createLink();
	hc = megerLink( ha, hb );
	printLink( hc );
	deleteLink( ha );
	deleteLink( hb );
	deleteLink( hc );
	return 0;

}

4.12、 有序表交集合并程序

描述

        有2个从小到大已经排序好的(有序)表,每个结点的数据是1个整数,已知两个表的数据存放在带头结点的单向链表中,将2个有序表合并成1个新的有序表,并要求新表中仅包含2个原表的交集。完成程序的编写。

输入

        输入4行,第1行有1个整数n,即第1个表的结点数,第2行有n个整数;第3行有1个整数m,即第2个表的结点数,第4行有m个整数。整数之间用空格隔开

输出

        输出1行,将上述2个表数据的交集从小到大排序输出,每个整数之后输出1个空格。

输入样例 1                                                                 输出样例 1

7                                              3 25 67 92
3 6 11 25 67 84 92
10
-5 3 8 25 25 43 67 92 96 99

具体实现

#include "stdio.h"
const int INF=0x7fffffff; //无穷大整数
struct ND
{	int data; 
	struct ND *next; 
};

ND *createLink( ) 
{	ND *head, *p;
	int n; 
    head = p = new ND; 
	scanf("%d", &n);
	while( n-- )
	{	p->next = new ND; 
		p = p->next;  
		scanf("%d", &p->data); 
	}
	p->next = NULL; 
	return head;    
}
void printLink( ND *head ) 
{	ND *p=head->next;  
	if( p==NULL )return ;
	while( p )
	{	printf( "%d ",p->data );
		p=p->next;
	}
	printf("\n");
}

void deleteLink( ND *head) 
{	ND *p=head;
	while( p )
	{	head = p->next;
		delete p;
		p = head;
	}
}

ND * megerLink( ND *ha, ND *hb ) //合并2有序表,返回合并后链表头结点的地址
{	ND *pa=ha->next, *pb=hb->next, *hc, *pc;
	int data, lastData=INF; //lastData为上一个结点的数据项,用于判定是否有相同数据
	hc=pc=new ND;
//************************************************

	while(pa || pb){
		if(pa&&(pb==NULL || pa->data<=pb->data)){
			if(pb&&pa->data==pb->data)
				data = pa->data;
			else
				data = -INF;
			pa=pa->next;
		}
		else{
			if(pa&& pa->data == pb->data)
				data=pa->data;
			else
				data =-INF;
			pb=pb->next;
		}
		if(data != -INF && data != lastData){
			pc->next=new ND;
			pc=pc->next;
			pc->data=data;
			lastData=data;
		}
	}

	pc->next=NULL;
	return hc;
}
int main()
{	ND *ha, *hb, *hc;
//	freopen( "sc6_6c.in", "r", stdin);
//	freopen( "sc6_6c.out", "w", stdout);
	ha = createLink();
	hb = createLink();
	hc = megerLink( ha, hb );
	printLink( hc );
	deleteLink( ha );
	deleteLink( hb );
	deleteLink( hc );
	return 0;
}

 5、银行ATM机业务

描述

        某银行有3台ATM机分别编号1、2、3,有n个客户要办理ATM机业务,按客户到达时间的先后顺序客户编号分别是1、2、3、……、n。已知每个客户到达时间Ti和办理ATM业务所需时间Ci(其中i=1、2、3、……、n),按客户离开时间顺序输出客户号、客户离开时间。排队规则:

1、队伍编号与ATM机编号一致(1号ATM机是1号队伍,……, 3号ATM机是3号队伍);

2、某客户到达时如果ATM机无人排队,则无需等待直接办理,如果有多台ATM机无人排队,选择编号较小的那台办理;

3、某客户到达时如果ATM机有人排队,则选择队伍短的排队,如果有多台ATM机队伍同样短,选择编号较小的那台排队;

4、如果某ATM机办理完业务后,该机子队伍较其他队伍短2人以上(队伍人数<=其他队伍人数-2),则最长队伍的队尾那个客户排入该ATM机(如果有多个同样长的最长队伍,则编号较小的那个队尾客户优先排入短队伍)。

5、如果第4个规则情况发生时,同时又有新客户来排队,规则4优先。

假设每个客户办理业务衔接时间为0(上个客户办理完业务后立即离开,下个客户马上办理业务)。

输入

        输入文件ATM.in包含n+1行数据,第一行是客户数n,接下去有n行数据每行2个整数(用空格隔开),分别是客户到达时间Ti和办理ATM业务所需时间Ci,n行数据已经按客户到达时间的顺序从小到大排序。

输出

        输出文件ATM.out包含n行数据,每行2个整数(用1个空格隔开),分别是客户号和该客户办理完成ATM业务的离开时间,n行数据按客户办理完ATM业务时间从小到大输出,如果有客户同时离开,则队伍号小的先输出。

输入样例 1                                                                 输出样例 1

10                                             1 40
30 10                                          4 45
33 30                                          3 52
37 15                                          5 62
37 5                                           2 63
41 17                                          6 66
43 3                                           7 68
45 6                                           9 71
48 50                                          10 86
49 3                                           8 102
50 20

具体实现
#include<stdio.h>
const int N0=1005;
const int INF=0x7fffffff;
struct Custom{
	int num,aTime,wTime,lTime;
};
struct ATM{
	Custom qu[N0];
  	int f,r;
}atm[4];

int n;

bool notEmpty(){
	for(int i=1;i<=3;i++)
      if(atm[i].r != atm[i].f)
        return true;
  	return false;
}
int minLeaveAtm(){
    atm[0].f=atm[0].r=0;
    atm[0].qu[atm[0].f].lTime=INF;
	int i,min=0;
    if( notEmpty()==false )
    	return 0;
    for( i=1; i<=3; i++ )
      if( atm[i].f!=atm[i].r &&
         atm[min].qu[atm[min].f].lTime>atm[i].qu[atm[i].f].lTime )
        min=i;
  return min;
}

void insertAtm( Custom t ){
    int i,min=0;
    atm[0].f=0;
    atm[0].r=1001;
    for( i=1; i<=3; i++ )
      if( atm[min].r-atm[min].f>atm[i].r-atm[i].f )
        min=i;
    if( atm[min].f==atm[min].r)
      t.lTime=t.aTime+t.wTime;
    else
      t.lTime=atm[min].qu[atm[min].r-1].lTime+t.wTime;
    atm[min].qu[atm[min].r++]=t;
} 

void deleteAtm(int k){
  if( atm[k].f==atm[k].r )
      return;
  Custom t;
  t=atm[k].qu[atm[k].f++];
    printf("%d %d\n",t.num, t.lTime );
  for( int i=1; i<=3; i++ )
    if( atm[i].r-atm[i].f-2>=atm[k].r-atm[k].f ){
      t=atm[i].qu[atm[i].r-1];
	  atm[i].r--;
      t.lTime=atm[k].qu[atm[k].r-1].lTime+t.wTime;
      atm[k].qu[atm[k].r++]=t;
      break ;
}
}
int main(){
	int aTime,wTime,i,k;
  	Custom t;
	scanf("%d",&n);
  	for(i=1;i<=n;i++){
    	t.num=i;
      	scanf("%d%d",&aTime,&wTime);
      	t.aTime=aTime;
      	t.wTime=wTime;
      
      	k=minLeaveAtm();
      	while(notEmpty() && atm[k].qu[atm[k].f].lTime<=aTime){
        	deleteAtm(k);
          	k=minLeaveAtm();
        }
      insertAtm(t);
    }
  while(notEmpty()){
  	k=minLeaveAtm();
    deleteAtm(k);
  }
  return 0;
}

6、多项式相乘 

描述

        编程实现若干个多项式相乘。多项式的输入输出格式为:系数在前,指数在后,各项按指数递增排列,每个多项式输入时以两个0结束。系数为0的项不输出。例如:1+4X^3-9X^5输入格式为:1 0 0 1 0 2 4 3 0 4 -9 5 0 0或者 1 0 4 3 -9 5 0 0,其输出只能是:1 0 4 3 -9 5

输入

        输入每行为一个多项式,多项式输入时以两个0结束。数据为若干行的多项式,例如:1 0 1 1 0 01 0 -1 1 0 01 0 1 2 0 0表示 (1+x)(1-x)(1+x^2)所有系数、指数均为整数(int类型)

输出

        输出包含1行,为上述多项式相乘结果。上例的输出为:1 0 -1 4表示1-x^4

输入样例 1                                                                 输出样例 1

1 0 1 1 0 0                                    1 0 -1 4
1 0 -1 1 0 0
1 0 1 2 0 0

具体实现

#include<stdio.h>
struct Poly{
	int c,e;
	Poly *next;
};
Poly *createPoly( ){
	int c,e;
  	Poly *head,*p;
  	head=p=new Poly;
  	while(true){
    	if(scanf("%d%d",&c,&e)!=2)
          break;
      	if(c==0 && e==0)
          break;
      	p->next=new Poly;
      	p=p->next;
      	p->c=c;
      	p->e=e;
    }
  p->next=NULL;
  return head;
}
void printPoly(Poly *head){
	Poly *p=head->next;
  	while(p){
    	printf("%d %d ",p->c,p->e);
      	p=p->next;
    }
  printf("\n");
}
void freePoly(Poly *head){
	Poly *p=head;
  	while(p){
    	head=head->next;
      	delete p;
      	p=head;
      }
}
Poly *addPoly( Poly *ha,Poly *hb){
	Poly *pa=ha->next,*pb=hb->next,*hc,*pc;
  	int c,e;
  	hc=pc=new Poly;
  	while(pa || pb){
    	if(pa && (pb == NULL || pa->e<pb->e)){
        	c=pa->c;
          	e=pa->e;
          	pa=pa->next;
        }else if(pb && (pa==NULL || pa->e>pb->e)){
        	c=pb->c;
          	e=pb->e;
          	pb=pb->next;
        }else{
        	c=pa->c+pb->c;
          	e=pa->e;
          	pa=pa->next;
          	pb=pb->next;
        }
        if(c){
        	pc->next=new Poly;
        	pc=pc->next;
        	pc->c=c;
        	pc->e=e;
		}
    }
    pc->next =NULL;
    return hc;
}
Poly *multyXmulty(Poly *ha,Poly *hb){
	Poly *oneXmulty(Poly *pa,Poly *hb);
  	Poly *hc,*ht,*ht1,*pa=ha->next;
  	hc= new Poly;
  	hc->next=NULL;
  	while(pa){
    	ht=oneXmulty(pa,hb);
      	ht1=hc;
      	hc=addPoly(hc,ht);
      	pa=pa->next;
      	freePoly(ht1);
      	freePoly(ht);
    }
  return hc;
}
Poly *oneXmulty(Poly *pa,Poly *hb){
	Poly *hc,*pc,*pb=hb->next;
  	hc=pc=new Poly;
  	while(pb){
    	pc->next =new Poly;
      	pc=pc->next;
      	pc->c=pa->c*pb->c;
      	pc->e=pa->e+pb->e;
      	pb=pb->next;
    }
  pc->next=NULL;
  return hc;
}
int main(){
//	Poly *ha,*hb,*hc;
	Poly *ha,*hc;
  	hc=createPoly();
  	ha=createPoly();
  	while(ha->next){
//    	hb=hc;
      	hc=multyXmulty(hc,ha);
//      	freePoly(hc);
      	freePoly(ha);
      	ha=createPoly();
    }
  printPoly(hc);
  freePoly(ha);
  freePoly(hc);
  return 0;
}

7、表达式求值

描述

        给一个表达式(字符串),求这个表达式的值。结果保留3位小数,第4位四舍五入。输入: 一个表达式。输出: 表达式的值。

输入

        输入是一个表达式。

输出

        输出有1个实数。

输入样例 1                                                                         输出样例 1

-34.1385*2^(-3.2)/2.9*4.5-6                        -11.765

具体实现

#include"stdio.h"
#include"math.h"
#include"string.h"
#define N0 105
struct OPstack{
	char data[N0];
	int top;
}op;
struct DataStack{
	double data[N0];
	int top;
}da;
char a[8][8]={
	'>','>','<','<','<','>','>','<',
	'>','>','<','<','<','>','>','<',
	'>','>','>','>','<','>','>','<',
	'>','>','>','>','<','>','>','<',
	'<','<','<','<','<','=','E','<',
	'>','>','>','>','E','>','>','>',
	'<','<','<','<','<','E','=','<',
	'>','>','>','>','<','>','>','<',
};
char b[9]="+-*/()#^";
int c[128]={0};
void init(){
	int i;
	for(i=0;i<8;i++)
		c[b[i]]=i;
}
char youXianJi(char ch1,char ch2){
	return a[c[ch1]][c[ch2]];
}
double cal (double a,char ch,double b){
	switch(ch){
		case'+':return a+b;
		case'-':return a-b;
		case'/':return a/b;
		case'*':return a*b;
		case'^':return pow(a,b); 
	}
}
double expression(char str[]){
	int i=0,j;
	char t[N0],ch;
	double a,b,r;
	strcat(str,"#");
	da.top = op.top=0;
	op.data[++op.top]='#';
	while (op.data[op.top]!='#'||str[i]!='#'){
		if(i==0&& str[i]=='-' || i>0 && str[i-1] == '(' && str[i] =='-')
			da.data[++da.top]=0;
		if(str[i]>='0' && str[i] <='9'|| str[i]=='.'){
			j=0;
			t[0]=0;
			while(str[i] >= '0' && str[i] <= '9' || str[i]=='.')
				t[j++]=str[i++];
			t[j]='\0';
			sscanf(t,"%lf",&r);
			da.data[++da.top]=r; 
		}
		else switch (youXianJi(op.data[op.top],str[i])){
			case'<': op.data[++op.top]=str[i];i++;break;
			case'=': op.top--;i++;break;
			case'>': b=da.data[da.top--];
					 a=da.data[da.top--];
					 ch=op.data[op.top--];
					 r=cal(a,ch,b);
					 da.data[++da.top]=r;
				break;
			default: printf("Error!\n");break; 
		}
	}
	return da.data[da.top]; 
}

int main(){
	char str[N0];
	gets(str);
	init();
	printf("%.3f\n",expression(str));
	return 0;
}

8、二叉树遍历

8.1、二叉树

描述

        已知二叉树的先序遍历序列和中序遍历序列,输出其后序遍历序列和层次序遍历序列。

输入

        输入有二行,分别是二叉树的先序遍历序列和中序遍历序列。

输出

        输出包含二行,分别是上述二叉树的后序遍历序列和层次序遍历序列。

输入样例 1                                                                 输出样例 1

abdeijfcgh                                     jifedhgcba
dijefbghca                                     abdcegifhj

具体实现

#include "stdio.h"
#include "string.h"
const int N0 = 105;

struct BinTree{
	char data;
	BinTree *lch,*rch;
}; 
void getString(char *layer ,char *mid ,char leftLayer[],char rightLayer[]){
	int i,j,k;
	for(i=j=k=0;layer[i];i++)
		if( strchr(mid,layer[i]))
			leftLayer[j++] = layer[i];
		else
			rightLayer[k++] = layer[i];
	leftLayer[j] = 0;
	rightLayer[k] = '\0';
}
BinTree *createBinTree(char *layer, char *mid ){
	BinTree *root;
	if( *layer == 0 || mid[0] == '\0')
		return NULL;
	char *p,leftLayer[N0],rightLayer[N0];
	int leftLen;
	p = strchr( mid , *layer);
	*p = '\0';
	leftLen = strlen( mid );
	root = new BinTree;
	root->data = *layer;
	getString(layer+1,mid,leftLayer,rightLayer);
	root->lch=createBinTree(leftLayer,mid);
	root->rch=createBinTree(rightLayer,p+1);
	return root;
}

void showTree(BinTree *root , int tab ,char ch){
	if( root == NULL)
		return ;
	for(int i = 1; i<=tab; i++)
		printf(" ");
	printf("%c(%c)\n",root->data,ch);
	showTree(root->lch,tab+5,'L');
	showTree(root->rch,tab+5,'R');
}
void preOrder( BinTree *root){
	if( root == NULL)
		return;
	printf("%c",root->data);
	preOrder(root->lch);
	preOrder(root->rch);
}
int high (BinTree *root){
	if(root == NULL)
		return 0;
	if(root->lch == NULL && root->rch == NULL)
		return 1;
	int lh = high (root->lch),rh = high(root->rch);
	return 1+(lh>rh?lh:rh);
}
int numLeave(BinTree *root){
	if(root == NULL)
		return 0;
	if(root->lch == NULL && root->rch == NULL)
		return 1;
	return numLeave(root->lch)+numLeave(root->rch);
}
int num[N0]={0};

void calculate(BinTree *root,int high){
	if(root == NULL)
		return ;
	num[high]++;
	calculate(root->lch,high+1);
	calculate(root->rch,high+1);
}

int main(){
	char layer[N0],mid[N0];
	BinTree *root;
	scanf("%[^\n]%*c", layer);
	scanf("%[^\n]%*c", mid);
	root = createBinTree( layer, mid);
	preOrder(root);printf("\n");
	calculate(root,1);
	for(int i = 1;num[i];i++)
		printf("%d ",num[i]);
	printf("\n");
	return 0;
}

8.2、二叉树D题

描述

        已知一颗二叉树的层次遍历序列和中序遍历序列,输出该树的先序遍历序列和该二叉树每一层的节点数。

输入

        输入二行,分别是一颗二叉树的层次遍历序列和中序遍历序列。

输出

        输出二行,分别是该树的先序遍历序列和该二叉树每一层的节点数。

输入样例 1                                                         输出样例 1

abdcegifhj                                abdeijfcgh
dijefbghca                                1 1 2 2 3 1

具体实现

#include "stdio.h"
#include "string.h"
const int N0 = 105;

struct BinTree{
	char data;
	BinTree *lch,*rch;
}; 
void getString(char *layer ,char *mid ,char leftLayer[],char rightLayer[]){
	int i,j,k;
	for(i=j=k=0;layer[i];i++)
		if( strchr(mid,layer[i]))
			leftLayer[j++] = layer[i];
		else
			rightLayer[k++] = layer[i];
	leftLayer[j] = 0;
	rightLayer[k] = '\0';
}
BinTree *createBinTree(char *layer, char *mid ){
	BinTree *root;
	if( *layer == 0 || mid[0] == '\0')
		return NULL;
	char *p,leftLayer[N0],rightLayer[N0];
	int leftLen;
	p = strchr( mid , *layer);
	*p = '\0';
	leftLen = strlen( mid );
	root = new BinTree;
	root->data = *layer;
	getString(layer+1,mid,leftLayer,rightLayer);
	root->lch=createBinTree(leftLayer,mid);
	root->rch=createBinTree(rightLayer,p+1);
	return root;
}

void showTree(BinTree *root , int tab ,char ch){
	if( root == NULL)
		return ;
	for(int i = 1; i<=tab; i++)
		printf(" ");
	printf("%c(%c)\n",root->data,ch);
	showTree(root->lch,tab+5,'L');
	showTree(root->rch,tab+5,'R');
}
void preOrder( BinTree *root){
	if( root == NULL)
		return;
	printf("%c",root->data);
	preOrder(root->lch);
	preOrder(root->rch);
}
int high (BinTree *root){
	if(root == NULL)
		return 0;
	if(root->lch == NULL && root->rch == NULL)
		return 1;
	int lh = high (root->lch),rh = high(root->rch);
	return 1+(lh>rh?lh:rh);
}
int numLeave(BinTree *root){
	if(root == NULL)
		return 0;
	if(root->lch == NULL && root->rch == NULL)
		return 1;
	return numLeave(root->lch)+numLeave(root->rch);
}
int num[N0]={0};

void calculate(BinTree *root,int high){
	if(root == NULL)
		return ;
	num[high]++;
	calculate(root->lch,high+1);
	calculate(root->rch,high+1);
}

int main(){
	char layer[N0],mid[N0];
	BinTree *root;
	scanf("%[^\n]%*c", layer);
	scanf("%[^\n]%*c", mid);
	root = createBinTree( layer, mid);
	preOrder(root);printf("\n");
	calculate(root,1);
	for(int i = 1;num[i];i++)
		printf("%d ",num[i]);
	printf("\n");
	return 0;
}

9、二叉树的应用

9.1、字母二叉排序树 

描述

        字母排序二叉树的每个节点由一个字母组成,且每个节点字母的ASCII码满足:

        左子树所有节点的值 < 根的值< 右子树所有节点的值

        下图一所示为一颗字母排序二叉树

image.png

        秋天到了,从每个树支最底层开始落叶,依次落下,如下图二所示

image.png

        每次落叶的字符串为:

                BDHPY

                CM

                GQ

                K

        给定一行字符串KQMPGCHDYB(其中没有相同的字母),根据输入字母的顺序,先建立字母排序二叉树(如图一),然后输出每层落叶的字符串。

输入

        输出文件只有一行字符串。

输出

        输出文件有若干行,分别是字母排序二叉树每次落叶的字符串。

输入样例 1                                                                 

KQMPGCHDYB                                     

输出样例 1

BDHPY
CM
GQ
K

具体实现

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N0 = 105;

struct BinSortTree {
    char data;
    BinSortTree* lch, * rch;
};

BinSortTree* createBinSortTree(string str) {
    BinSortTree* root = NULL, * p, * parent;
    for (int i = 0; i < str.length(); i++) {
        if (root == NULL) {
            root = new BinSortTree;
            root->data = str[i];
            root->lch = root->rch = NULL;
        }
        else {
            parent = NULL;
            p = root;
            while (p) {
                parent = p;
                if (str[i] < p->data)
                    p = p->lch;
                else
                    p = p->rch;
            }
            p = new BinSortTree;
            p->data = str[i];
            p->lch = p->rch = NULL;
            if (str[i] < parent->data)
                parent->lch = p;
            else
                parent->rch = p;
        }
    }
    return root;
}

void showTree(BinSortTree* root, int tab) {
    if (root == NULL)
        return;
    printf("%*c%c\n", tab, ' ', root->data);
    showTree(root->lch, tab + 5);
    showTree(root->rch, tab + 5);
}

void preOrder(BinSortTree* root) {
    if (root == NULL)
        return;
    printf("%c", root->data);
    preOrder(root->lch);
    preOrder(root->rch);
}

int main() {
    string str = "";
    string temp;
    BinSortTree* root;
    while (getline(cin, temp)) {
        if (temp.empty())
            continue;
        str += temp;
    }

    reverse(str.begin(), str.end()); // 倒叙

    root = createBinSortTree(str);
    preOrder(root);
    printf("\n");
    return 0;
}

 9.2、落叶纷纷

描述

        深秋悄然而至,树叶飘落层层叠叠,给大地铺上了五彩缤纷的地毯。

        字母排序二叉树,每个节点由一个字母组成,且每个节点字母的ASCII码满足:

        左子树所有节点的值<根的值<右子树所有节点的值

        下图一所示为一颗字母排序二叉树

image.png

        秋天到了,从每个树支最底层开始落叶,依次落下(如图二所示)

image.png

        下面是每次落叶的字符串

                BDHPY

                CM

                GQ

                K

        已知上面每次落叶的字符串,输出该二叉树的先序遍历序列。

输入

        输入文件有若干行,分别是字母排序二叉树每次落叶的字符串。

输出

        输出文件只有一行,是该字母排序二叉树的先序遍历序列。

输入样例 1                                                         输出样例 1

BDHPY                                     KGCBDHQMPY
CM
GQ
K

具体实现

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N0 = 105;

struct BinSortTree {
    char data;
    BinSortTree* lch, * rch;
};

BinSortTree* createBinSortTree(string str) {
    BinSortTree* root = NULL, * p, * parent;
    for (int i = 0; i < str.length(); i++) {
        if (root == NULL) {
            root = new BinSortTree;
            root->data = str[i];
            root->lch = root->rch = NULL;
        }
        else {
            parent = NULL;
            p = root;
            while (p) {
                parent = p;
                if (str[i] < p->data)
                    p = p->lch;
                else
                    p = p->rch;
            }
            p = new BinSortTree;
            p->data = str[i];
            p->lch = p->rch = NULL;
            if (str[i] < parent->data)
                parent->lch = p;
            else
                parent->rch = p;
        }
    }
    return root;
}

void showTree(BinSortTree* root, int tab) {
    if (root == NULL)
        return;
    printf("%*c%c\n", tab, ' ', root->data);
    showTree(root->lch, tab + 5);
    showTree(root->rch, tab + 5);
}

void preOrder(BinSortTree* root) {
    if (root == NULL)
        return;
    printf("%c", root->data);
    preOrder(root->lch);
    preOrder(root->rch);
}

int main() {
    string str = "";
    string temp;
    BinSortTree* root;
    while (getline(cin, temp)) {
        if (temp.empty())
            continue;
        str += temp;
    }

    reverse(str.begin(), str.end()); // 倒叙

    root = createBinSortTree(str);
    preOrder(root);
    printf("\n");
    return 0;
}

10、哈夫曼树及编码

描述

        给定一篇用于通信的英文电文,统计该电文中每个字符出现的频率,按频率左小右大的方法为这些字符建立哈夫曼(Huffamn)树,并编出每个字符的哈夫曼树码,输出该电文的哈夫曼码译文。

输入

        一篇用于通信的英文电文

输出        

        输出该电文的哈夫曼码译文

输入样例 1                                                                         输出样例 1

aaccdddbacbcddddddd                                011011000011101001100010001111111

具体实现

#include<stdio.h>

const int N0 = 300; 
const int INF = 0X7fffffff;

struct HuffmanTree{
	int w,lch,rch,parent;
}ht[2*N0];

char str[1000000];

struct HuffmanCode{
	char ch,code[N0];
	int start;
}hc[N0];

int root,n;//根与叶子数

//读数据 
void readData(){
	char ch;
	int t[N0]={0},j=0;
	n=0;
	while(scanf("%c",&ch) == 1){
		t[ch]++;//t[97] = 3 
		str[j++] = ch;
	}
	str[j] = '\0';
	for(int i = 0; i <= 255; i++){
		if(t[i]){
			n++;
			ht[n].w = t[i];
			hc[n].ch = i;
		} 
	root = 2*n-1;
	}
}

//查找最小与次小下标 
void seekMin12(int t,int &s1,int &s2){
	s1 = s2 = 0;
	ht[s1].w = ht[s2].w=INF;
	for(int i =1;i<=t;i++){
		if( ht[i].parent == 0)
			if(ht[i].w < ht[s1].w){
				s2=s1;
				s1=i;
			}else if(ht[i].w < ht[s2].w)
				s2 =i;
	}
}

//创建哈夫曼树 
void createHuffmanTree(){
	int i , s1 , s2;//s1-->最小下标  s2-->次最小的下标 
	for(i = n+1; i<=root; i++){
		seekMin12( i-1, s1, s2);
		ht[i].w = ht[s1].w + ht[s2].w;
		ht[i].lch = s1;
		ht[i].rch = s2;
		ht[s1].parent = ht[s2].parent = i;
	} 
}


//编码函数 
void createHuffmanCode(){
	int child,parent;
	for(int i =1 ;i <= n;i++){
		child = i;//从叶子开始建,叶子就是孩子
		hc[i].start = 0;//码的长度置零 
		parent = ht[child].parent;
		while( child != root){
			if( child == ht[parent].lch)
				hc[i].code[hc[i].start++] = '0';
			else
				hc[i].code[hc[i].start++] = '1';
			child = parent;
			parent = ht[child].parent;
		} 
		
	}
}


//加密转化
void txtToCode(char str[]){
	for(int i = 0; str[i]; i++)
		for(int j =1; j<=n; j++ )
			if(str[i] == hc[j].ch){
				for(int k = hc[j].start-1;k >= 0; k--){
					putchar( hc[j].code[k]);
				}
				break;
			}
} 

int main(){
	readData();
	createHuffmanTree();
	createHuffmanCode();
	txtToCode(str);
	return 0;
}

11、迪杰斯特拉最短路径

描述

        You are a spy, and you have stolen some top secret of the enemy, now you are to find a way which takes you least time to escape.There are some many cross-points and some many roads, even two cross-points there can be multiple roads. You can assume that the cross-points are numbered from 1 to n. Cross-point 1 is your starting point and you need to go to cross-point n. All roads are bidirectional.

输入

        The first line contains two integers n and m(1≤n≤200, 0≤m≤10000), number of cross-points and number of roads respectively. Next m lines has three integers i, j, k ( i≠j, 1≤k≤10000), indicating there is a road of length k connecting cross-point i to cross-point j.

输出

        Output one number, the shortest distance from cross-point 1 to corss-point n. If there is no path exist, output -1. No extra spaces are allowed.

输入样例 1                                                                         输出样例 1

4 6                                                 13
1 2 5
1 3 4
2 4 8
3 4 9
1 2 10
2 4 11

具体实现

#include "stdio.h"
const int N0=205;
const int INF=0x7fffffff;
int adjMatrix[N0][N0];
int n, m;
void readData(){
	int i,j,w;
	scanf("%d%d",&n, &m);
	for(i = 1;i<=n;i++)
		for(j =1;j<=n;j++)
			if(i==j)
				adjMatrix[i][j]=0;
			else
				adjMatrix[i][j]=INF;
	while(m--){
		scanf("%d%d%d",&i,&j,&w);
		if(w<adjMatrix[i][j])
			adjMatrix[i][j]=adjMatrix[j][i]=w;		
	}			
}
void dijkstra(int x){
	int mark[N0]={0},path[N0],dist[N0];
	int i,j,min;
	for(i=1;i<=n;i++){
		path[i]=x;
		dist[i]=adjMatrix[x][i];
	}
	mark[x]=1;
	for(i=2;i<=n;i++){
		min=0;
		dist[0]=INF;
		for(j=1;j<=n;j++)
			if(mark[j]==0 && dist[j]<dist[min])
				min = j;
		if(min==0)	
			break;
		mark[min]=1;
		for(j=1;j<=n;j++)
			if(mark[j]==0 && dist[j]>(double)dist[min]+adjMatrix[min][j]){
				dist[j]=dist[min]+adjMatrix[min][j];
				path[j]=min;
			}	
	}
	if(dist[n]!=INF)
		printf("%d\n",dist[n]);
	else
		printf("-1\n");
	}
int main(){
	readData();
	dijkstra(1);
	return 0;

}

12、搜索

12.1、地图面积

描述

        一个长方形地图,由n×m个面积相同的正方形小方格组成,小方格有4种颜色,分别用字符'%'、'+'、'#'、和'.'表示,连续一片相同颜色的区域构成一个城镇,求最大城镇的面积。

输入

        输入文件第1行有2个整数,分别是n、m;接下来有n行,每行有m个小方格分别用字符'%'、'+'、'#'、和'.'表示不同颜色。

输出

        输出文件有一个整数,是地图中最大城镇的面积。

输入样例 1                                                                         输出样例 1

9 11                                                27
%%++%%%%++%
%%%%++++%+%
%++#%###.##
%%+#%#.....
%+%%...###.
%+%.%%..#..
++#.##.###.
+%.#.....#.
++.#.#....#

具体实现

#include "iostream"
#include "queue"
#include "string"
#include "map"//键值对映射(是在数组的索引值与内容之间的关系的拓展) 

using namespace std;

int dRow[4] = {0, 0, 1, -1};
int dCol[4] = {1, -1, 0, 0};//方向数组 
string goNext(string str, int dir){
	int row, col, space;//s="1234678.",space = 8
	space = str.find(".");
	row = space / 3 + dRow[dir];
	col = space % 3 + dCol[dir];
	if(row < 0 || row > 2 || col < 0 || col >2)
		return "empString";
	swap(str[space], str[row * 3 + col % 3]);//row%3超出边界 
	return str;
}
int bfs(string begin, string end){//广度优先 
	queue <string> qu;
	map<string,int> step;//string是字符串,int是对应的步数 
	qu.push(begin);
	step[begin] = 0;
	string str, testStr;
	while(!qu.empty()){
		str = qu.front();
		qu.pop();
		if(str == end )
			return step[str];
		for(int i = 0; i < 4; i++){
			testStr = goNext(str, i);//返回一个字符串 
			if(testStr == "empString" || step[testStr] > 0)
				continue;
			qu.push(testStr);
			step[testStr] = step[str] + 1;//步长加一 
		}
	}
	return 0;
}


int main(){
	string begin, end;
	cin>>begin>>end;
	cout<<bfs(begin, end)<<endl;
	return 0;
}

12.2、迷宫最短路

描述

        给定一个n*m大小的迷宫,其中“*”代表不可通过的墙壁,而“.”代表平地,S表示起点,T代表终点。移动过程中,如果当前位置是(x,y)(下标从0开始),且每次只能前往上下左右:(x,y+1)、(x,y-1)、(x-1,y)、(x+1,y)四个位置的平地,求从起点S到达终点T的最少步数。

输入

        输入文件有n+2行数据,第1行有2个整数,分别是迷宫的n行、m列;接下来有n行,每行有m个字符,表示迷宫地图。最后1行是4个整数,分别是起点和终点位置。

maze.png

输出

        输出文件有一个整数,是从起点S到达终点T的最少步数。

输入样例 1                                                         输出样例 1

5 5                                        11
.....
.*.*.
.*.*.
.***.
....*
2 2 4 3

具体实现

#include "iostream"
#include "queue"
#include "string"
#include "map"//键值对映射(是在数组的索引值与内容之间的关系的拓展) 

using namespace std;

int dRow[4] = {0, 0, 1, -1};
int dCol[4] = {1, -1, 0, 0};//方向数组 
string goNext(string str, int dir){
	int row, col, space;//s="1234678.",space = 8
	space = str.find(".");
	row = space / 3 + dRow[dir];
	col = space % 3 + dCol[dir];
	if(row < 0 || row > 2 || col < 0 || col >2)
		return "empString";
	swap(str[space], str[row * 3 + col % 3]);//row%3超出边界 
	return str;
}
int bfs(string begin, string end){//广度优先 
	queue <string> qu;
	map<string,int> step;//string是字符串,int是对应的步数 
	qu.push(begin);
	step[begin] = 0;
	string str, testStr;
	while(!qu.empty()){
		str = qu.front();
		qu.pop();
		if(str == end )
			return step[str];
		for(int i = 0; i < 4; i++){
			testStr = goNext(str, i);//返回一个字符串 
			if(testStr == "empString" || step[testStr] > 0)
				continue;
			qu.push(testStr);
			step[testStr] = step[str] + 1;//步长加一 
		}
	}
	return 0;
}


int main(){
	string begin, end;
	cin>>begin>>end;
	cout<<bfs(begin, end)<<endl;
	return 0;
}

12.3、八数矩阵

描述

        如下第一个图3×3矩阵的9个格子中,放着1~8的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

捕获.JPG

        第一个图的局面记为:12345678.

        第二个图的局面记为:123.46758

        显然是按从上到下,从左到右的顺序记录数字,空格记为句点“.”。

        本题目的任务是已知八数矩阵的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

输入格式

        输入第一行包含八数矩阵的初态,第二行包含八数矩阵的终态。

输出格式

        输出最少的步数,如果不存在方案,则输出-1。

输入

        输入文件有2行,分别是八数矩阵的初态和终态。

输出

        输出文件有一个整数,是初态到终态最少移动的步数。

输入样例 1                                                 输出样例 1

12345678.                             3
123.46758

具体实现

#include "iostream"
#include "queue"
#include "string"
#include "map"//键值对映射(是在数组的索引值与内容之间的关系的拓展) 

using namespace std;

int dRow[4] = {0, 0, 1, -1};
int dCol[4] = {1, -1, 0, 0};//方向数组 
string goNext(string str, int dir){
	int row, col, space;//s="1234678.",space = 8
	space = str.find(".");
	row = space / 3 + dRow[dir];
	col = space % 3 + dCol[dir];
	if(row < 0 || row > 2 || col < 0 || col >2)
		return "empString";
	swap(str[space], str[row * 3 + col % 3]);//row%3超出边界 
	return str;
}
int bfs(string begin, string end){//广度优先 
	queue <string> qu;
	map<string,int> step;//string是字符串,int是对应的步数 
	qu.push(begin);
	step[begin] = 0;
	string str, testStr;
	while(!qu.empty()){
		str = qu.front();
		qu.pop();
		if(str == end )
			return step[str];
		for(int i = 0; i < 4; i++){
			testStr = goNext(str, i);//返回一个字符串 
			if(testStr == "empString" || step[testStr] > 0)
				continue;
			qu.push(testStr);
			step[testStr] = step[str] + 1;//步长加一 
		}
	}
	return 0;
}


int main(){
	string begin, end;
	cin>>begin>>end;
	cout<<bfs(begin, end)<<endl;
	return 0;
}

13、整数分划

描述

        整数的分划问题, 如对于正整数n=6,可以分划为:

                6

                5+1

                4+2, 4+1+1

                3+3, 3+2+1, 3+1+1+1

                2+2+2, 2+2+1+1, 2+1+1+1+1

                1+1+1+1+1+1+1

        现在的问题是,对于给定的正整数n,编写程序计算出其分划的数目。

输入

        1个整数n , 0<= n <= 300

输出

        1个整数,为正整数n分划的得数目

输入样例 1                                                 输出样例 1

26                                    2436

具体实现

#include"stdio.h"

#define N0 1500

char a[N0][N0][50];
char* strrev(char* str) {
  if (!str) return NULL;

  char* p1 = str;
  char* p2 = str + strlen(str) - 1;
  while (p2 > p1) {
    char tmp = *p1;
    *p1++ = *p2;
    *p2-- = tmp;
  }
  return str;
}
void add(char c[], char a[], char b[]){
	int la = strlen(a), lb = strlen(b);
	int i, j, t, k;
	for( i = 0; i < 50; i++)
		c[i] = '0';
	for(k = 0,i = la-1, j = lb -1;i >= 0 || j >= 0; i--, j--, k++){
		if(i >= 0 && j >= 0)
			t = a[i]-'0'+b[j]-'0';
		else if (i >= 0)
			t = a[i] - '0'; 
		else
			t = b[j] - '0';
		c[k] = c[k] + t % 10;
		c[k+1] = t / 10 + '0';
	}
	if( c[k] != '0')
		c[k+1] = 0;
	else
		c[k] = 0;	
	strrev(c);
}
char *q3(int n, int m){
 	if(n == 0 || m == 0)
 		return "1";
 	for(int i = 0; i <= n; i++)
 		strcpy(a[i][0], "0");
 	for(int i = 0; i<= m; i++)
 		strcpy(a[0][i], "0");
 	for(int i = 1; i<=n; i++)
 		for(int j = 1; j<=m; j++)
 			if(i == 1 || j == 1)
 				strcpy(a[i][j], "1");
 			else if(j >= i)
 				add(a[i][j], "1", a[i][i-1]);
 			else
 				add(a[i][j], a[i][j-1], a[i-j][j]);
 	return a[n][m];
 }
int main(){
	int n;
	scanf("%d",&n);
	printf("%s\n",q3(n,n));
	return 0;
}

  • 25
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-Z_Nuyoah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值