【濡白的C语言】从零开始的刷题之旅

前言

每个人都是从小白成长起来的,在此篇记录一些我从小白开始刷到的一些有意义的题目,不定期更新题目,建议点赞+收藏后享用~感谢支持!,也欢迎评论出想看的题目类型,会考虑添加的!
题目的话我会给出题干,代码,最后附上我对题目值得注意或学习的地方。当然有的题目只是单纯觉得比较锻炼能力,所以不会有什么评价。

目录

简单部分

圆柱体的表面积

温度转换

鸡兔同笼

倒三角形

分数化小数

排列

开灯问题

中等难度

蛇形填数

竖式问题

TeX中的引号

回文词与镜像串

循环小数

困难部分

周期串

 分子量

谜题

纵横字谜的答案

特别困的学生

洪水!

 综合

扫雷(可连续展开)

象棋(判断残局)


简单部分

圆柱体的表面积

输入底面半径r和高h,输出圆柱体的表面积,保留3位小数

#include<stdio.h>

int main()
{
    double pi = 3.1415926;//此处可以用反三角函数求,如 pi = acos(-1.0),acos在math库下
    double r, h, s1, s2, s;
    scanf("%lf%lf", &r, &h);
    s1 = pi * r * r;
    s2 = 2 * pi * r * h;
    s = s1 * 2.0 + s2;
    printf("Area = %.3lf\n", s)
    return 0;
}

1.变量是死的,不赋值就不会改变,即a = 2 * b,当你改变b的值后,a不会发生改变,除非你再次对a赋值

2.scanf的输入格式要注意,当你选择scanf("%d,%d", &a, &b)时,输入时只能按照一样的格式 1,5不能将','省略

3.关于输出的格式,%a.b f(a,b为常数),表示输出占a格,保留小数点后b位,更多具体用法可以在遇见时再来搜索

温度转换

输入华氏温度F,将其转换为摄氏温度C,已知C = 5 * (F - 32) / 9

#include<stdio.h>

int main()
{
    doule F = 0, C = 0;
    scanf("%d", &F);
    C = 5.0 / 9.0 * (F - 32);
    printf("%lf", C);
    return 0;
}

一个初学者很容易犯的错误,为什么这里要写成5.0 / 9.0而不是5 / 9呢?因为5和9都是整形,相除得到的结果也是整形,就是只会保留整数部分0,那么5 / 9  就变成0了,但是如果有浮点型参与进来,那么运算结果就是浮点型,5.0是有小数部分的,属于浮点型,所以5.0 / 9.0结果不会取0

鸡兔同笼

已知鸡和兔的总数量为n,总腿数为m。输入n和m,依次输出鸡的数目和兔的数目。如 果无解,则输出No answer

#include<stdio.h>

int main()
{
    int a, b, n, m;
    scanf("%d%d", &n, &m);
    a = (4*n-m)/2;
    b = n-a;
    if(m % 2 == 1 || a < 0 || b < 0)
        printf("No answer\n");
    else
        printf("%d %d\n", a, b);
    return 0;
}


//设鸡有a只,兔有b只,则a+b=n,2a+4b=m,联立解得a=(4n-m)/2,b=n-a
//判定有解的两个条件:a和b都是整数;其次,a和b必须是非负的

1.对于许多不理解的符号要学会自己去搜,比如此题中的'%',这是一个良好的习惯,就像我一个学姐说的“能百度就不问,再问敲脑阔”哈哈哈哈哈

2.分支语句 if - else if - else:基本用法是if (条件){执行语句}; else if (条件) {执行语句}; else {执行语句},值得注意的是 if - else if - else 中每一个只能管理一句话,如果要执行多句话就需要用{}括起来,否则就会出现if(a) b; c; b语句可能执行,但c语句一定执行。

3.注意 || 与 && 都是短路运算符,即 a||b,一旦a成立那么b将不再执行或判断,同理 a&&b,一旦a为假,则b不在参与运算或判断。

倒三角形

输入正整数n≤20,输出一个n层的倒三角形

#include<stdio.h>

int main()
{
    int a, c;
    scanf("%d", &a);
    c = a;
    while (c >= 0)
    {
        for (int b = c; b >= 1; b--)
        {
            printf("#");
        }
        c -= 2;
        printf("\n");
        for (int d = a - c; d >= 1; d -= 2)
        {
            printf(" ");
        }
    }
    return 0;
}

很经典的一题,但是不认为有什么值得注意的细节

分数化小数

输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b≤10 6,c≤100。输 入包含多组数据,结束标记为a=b=c=0。

#include<stdio.h>

int main()
{
    int a, b, c, m;
    float e = 1;
    scanf("%d%d%d", &a, &b, &c);
    printf("%d", a / b);
    if (c == 0) m = 1;
    else
    {
        printf(".");
        for (int i = 1; i <= c - 1; i++)
        {
            e *= 10.0;
            int d = (int)(e * a / b) % 10;
            printf("%d", d);
        }
        if ((int)(e * 10 * a / b) % 10 > 5)
            printf("%d", (int)(e * a / b) % 10 + 1);
        else
            printf("%d", (int)(e * 10 * a / b) % 10);
    }
    return 0;
}

1.while(1)是一个经典的死循环,简单设置一个break即可跳出,值得注意的是区分break和continue break是跳出当前所在循环,continue是跳过此次循环的后部分,重新开始判断部分

2.C语言中无论是整形还是浮点型都是有一定范围的,超出这个范围时,就要学会利用*10,/10,%10等操作来实现更大范围的运算,当然,之后还会遇到字符数字相乘

排列

用1,2,3,…,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要 求abc:def:ghi=1:2:3。按照“abc def ghi”的格式输出所有解,每行一个解。

//方法一(以数组的方式,统计每个数字是否只出现过一次)
#include<stdio.h>

int main()
{
    int s[10], a, b, c;
    for (a = 123; a < 333; a++)
    {
        for (int m = 0; m < 10; m++)
            s[m] = 0;//将数组中1-9的值定为0
        s[a / 100] = 1;
        s[a / 10 % 10] = 1;
        s[a % 10] = 1;
        b = a * 2;
        s[b / 100] = 1;
        s[b / 10 % 10] = 1;
        s[b % 10] = 1;
        c = a * 3;
        s[c / 100] = 1;
        s[c / 10 % 10] = 1;
        s[c % 10] = 1;//重新定义出现的元素值为1(无论出现多少次)
        int sum = 0;
        for (int m = 1; m < 10; m++)
            sum += s[m];//使每个元素的值相加
        if (sum == 9)//若每个元素都出现过一次,则为9
            printf("%d %d %d\n", a, b, c);
    }
    return 0;
}



//方法二(判断九个数字相乘相加的值)
#include<stdio.h>

int main()
{
	for (int a = 123; a < 329; a++)
	{
		if (a / 100 + a / 10 % 10 + a % 10 + a * 2 / 100 + a * 2 / 10 % 10 + a * 2 % 10 + a * 3 / 100 + a * 3 / 10 % 10 + a * 3 % 10 == 45 && (a / 100) * (a / 10 % 10) * (a % 10) * (a * 2 / 100) * (a * 2 / 10 % 10) * (a * 2 % 10) * (a * 3 / 100) * (a * 3 / 10 % 10) * (a * 3 % 10) == 362880)
			printf("%d %d %d\n",a,a*2,a*3);
	}
	return 0;
}

编程的目的应该是锻炼思维,而不是单纯结出题目,此题最难的部分大概就是如何判断每个数字各使用一次,除了上述方法,还可以用数组记录,比如如果1出现过那么arr[1 - 1]++,最后判断一下arr[0] - arr[9]是不是均为1即可

开灯问题

开灯问题。有n盏灯,编号为1~n。第1个人把所有灯打开,第2个人按下所有编号为2 的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯 将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?输 入n和k,输出开着的灯的编号。k≤n≤1000。

#include<stdio.h>

char a[1000];

int main()
{
	memset(a, 1, sizeof(a));
	int n, m, x, y;
	scanf("%d%d", &n, &m);
	for (x = 2; x <= m; x++)
		for (y = 1; y <= n; y++)
		{
			if (y % x == 0)
				a[y] = !a[y];
		}
	for (x = 1; x < n; x++)
	{
		if (a[x] == 1)
			printf("%d ", x);
	}
	if(a[n] == 1)
		printf("%d", n);
	return 0;
}

1.如何表示开关呢?最简单的方式就是01,一个为假一个为真,非0为真,因为k = !k可以轻松表示开灯关灯

2.对于数组,就是一连串的数,存放在一个特定的空间内,要注意的是数组下标从0开始,即定义arr[10],只存在arr[0] - arr[9],而不存在arr[10],同时定义时要注意,大多数时候数组的大小必须用常量表达式,即int n; int arr[n]是不被允许的,因为n是一个变量,但是对于经常用到的数组大小,可以使用#define n 10     int arr[n]来定义,这叫做宏替换,对于一些使用数组较多的程序而言,宏替换是相当有必要的

中等难度

蛇形填数

在n×n方阵里填入1,2,…,n×n,要求填成蛇形。

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

#define maxn 20

int a[maxn][maxn];

int main()
{
    int n, x, y, tot = 0;
    scanf("%d", &n);
    memset(a, 0, sizeof(a));
    tot = a[x=0][y=n-1] = 1;
    while(tot < n*n)
    {
        while(x+1<n && !a[x+1][y]) a[++x][y] = ++tot;
        while(y-1>=0 && !a[x][y-1]) a[x][--y] = ++tot;
        while(x-1>=0 && !a[x-1][y]) a[--x][y] = ++tot;
        while(y+1<n && !a[x][y+1]) a[x][++y] = ++tot;
    }
    for(x = 0; x < n; x++)
    {
        for(y = 0; y < n; y++) 
        printf("%3d", a[x][y]);
        printf("\n");
    }
    return 0;
}

 1.合理利用判断真假,如已经赋值过就不会是原来的0,进而变为真,所以加上' ! '判断为假,即未赋值的时候赋值

2.合理利用短路运算符,也许你会担心第一次到达边界的时候判断真假会出现越界行为,但是由于短路运算符的存在,先进行判断时候到达边界,若到达边界即为假,所以不必担心

竖式问题

找出所有形如abc*de(三位数乘以两位数)的算式,使得在完整的竖式中, 所有数字都属于一个特定的数字集合。输入数字集合,输出所有 竖式。每个竖式前应有编号,之后应有一个空行。例如输入12345,式子中只能出现12345这些数字。最后输出解的总数。

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

int main()
{
    int count = 0;
    char s[20], buf[99];
    scanf("%s", s);
    for(int abc = 111; abc <= 999; abc++)
    for(int de = 11; de <= 99; de++)
    {
        int x = abc*(de%10), y = abc*(de/10), z = abc*de;
        sprintf(buf, "%d%d%d%d%d", abc, de, x, y, z);
        int ok = 1;
        for(int i = 0; i < strlen(buf); i++)
            if(strchr(s, buf[i]) == NULL) ok = 0;
        if(ok)
        {
            printf("<%d>\n", ++count);
            printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n", abc, de, x, y, z);
        }
    }
    printf("The number of solutions = %d\n", count);
    return 0;
}

1.就像前面说的,遇到没见过的运算符第一时间不是问,而是去自己搜,因此不会解释sprintf的用法,只是提出可以利用%10不断提出一个数字存入数组

2.初学者很容易将两个字符串之间用’==‘进行比较,即使了解之后也偶尔会犯错,作者是在一次写程序中用了近30多此比较后,忽然发现用错了才留下深刻印象的

TeX中的引号

在TeX中,左双引号是“``”,右双引号是“''”。输入一篇包含双引号的文章,你的任务是 把它转换成TeX的格式。

#include<stdio.h>

int main()
{
    int c, q = 1;
    while((c = getchar()) != EOF) 
    {
        if(c == '"') 
        { 
            printf("%s", q ? "``" : "''"); 
            q = !q; 
        }
        else 
            printf("%c", c);
    }
    return 0;
}

1.a ? b : c名叫三目运算符,初学者可能觉得没什么用,但是有时候确实比if - else要快捷很多

2. != EOF可以理解为只要接收到了正确的数据,就会继续下去,之所以在此处用getchar是因为scanf无法读取包含空格的字符串,通常用fgets读取一行,但是在此介绍一种正则表达式%[^\n],表示一直读取直到遇见’\n‘,但是值得注意的是缓冲区会留下一个 '\n'通常需要getchar读取掉,不然会发生很多不必要的错误

回文词与镜像串

输入一个字符串,判断它是否为回文串以及镜像串。输入字符串保证不含数字0。下图为镜像对照表。

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

char* rev = "A 3 HIL JM O 2TUVWXY51SE Z 8 ";

char* msg[] = {"not a palindrome", "a regular palindrome", "a mirrored string", "a mirrored palindrome"};

char r(char ch) 
{
    if(isalpha(ch)) 
        return rev[ch - 'A'];
    return rev[ch - '0' + 25];
}

int main() 
{
    char s[30];
    while(scanf("%s", s) == 1) 
    {
        int len = strlen(s);
        int p = 1, m = 1;//假定为镜像串且为回文词
        for(int i = 0; i < (len+1)/2; i++) 
        {
            if(s[i] != s[len-1-i]) 
                p = 0; //不是回文串
            if(r(s[i]) != s[len-1-i]) 
                m = 0; //不是镜像串
        }
    printf("%s -- is %s.\n\n", s, msg[m*2+p]);
    }
    return 0;
}

回文词和镜像串都是非常经典的题目,建议好好理解此处函数r的用法,可以理解为一种哈希,非常有用的数据结构

循环小数

输入整数a和b(0≤a≤3000,1≤b≤3000),输出a/b的循环小数表示以及循环节长度。例 如a=5,b=43,小数表示为0.(116279069767441860465),循环节长度为21。

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

int a[1005] = { 0 }, b[1005] = { 0 }, c[1005] = { 0 };
//a用来存放除得结果
//b用来存放被除数
//c用来存放被除数对应下标,以计循环位

int main()
{
    int m, n, count = 0, i, x, y;
    scanf("%d%d", &m, &n);
    x = m, y = n;
    a[count++] = m / n;
    m = m % n;
    while (!c[m])
    {
        c[m] = count;
        b[count] = m;
        a[count++] = 10 * m / n;
        m = 10 * m % n;                                               
    }
    printf("%d/%d=%d.", x, y, a[0]);
    for (i = 1; i < count && i < 50; i++)
    {
        if (b[i] == m)
            printf("(");
        printf("%d", a[i]);
    }
    printf(")\n");
    printf("循环位数是%d位", count - c[m]);
}

 之前提过的如何解决浮点数有一定范围问题,并且判断循环的方式很有意思,很多时候编程就是这样,想了好久,忽然看了别人的解答就发现,原来是这么一回事,其实也不难

困难部分

周期串

如果一个字符串可以由某个长度为k的字符串重复多次得到,则称该串以k为周期。例 如,abcabcabcabc以3为周期(注意,它也以6和12为周期)。 输入一个长度不超过80的字符串,输出其最小周期。

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

int main()
{
	char a[85];
	int n, m, k = 2;
	scanf("%s", a);
	for (n = 1; n < strlen(a); n++)
	{
		if (a[0] == a[n])
		{
			k = 1;
			for (m = 1; n + m < strlen(a); m++)
			{
				if (a[m] != a[n + m])
					k = 0;
			}
		}
		if (k == 1)
		{
			printf("%d", n);
			break;
		}
	}
	return 0;
}

 分子量

给出一种物质的分子式(不带括号),求分子量。本题中的分子式只包含4种原子,分 别为C, H, O, N,原子量分别为12.01, 1.008, 16.00, 14.01(单位:g/mol)。例如,C6H5OH的 分子量为94.108g/mol。

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

int main()
{
	char a[1000],b;
	int i=0,num;
	double n,sum=0;
	scanf("%[^\n]",a);
	b = a[i];
	while (b != '\0')
	{
		num = 1;
		switch (b)
		{
			case 'C':n = 12.01; break;
			case 'H':n = 1.008; break;
			case 'O':n = 16.00; break;
			case 'N':n = 14.01; break;
		}
		if (a[i + 1] >= '0' && a[i + 1] <= '9')
		{
			i++;
			num = a[i] - '0';
			while (a[i + 1] >= '0' && a[i + 1] <= '9')
			{
				num *= 10;
				num += a[i + 1] - '0';
				i++;
			}

		}
		sum += num * n;
		b = a[++i];
	}
	printf("%.3lf", sum);

}

感兴趣可以在多添加几个元素进去,同时区分大小写加入Cu,Pt这样的,题目的难点在于从中提取出每个元素后面的数字大小,在此提出用getchar读取的一种可行方案

谜题

有一个5*5的网格,其中恰好有一个格子是空的,其他格子各有一个字母。一共有4种指 令:WASD,分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格,此后每输入一次指令移动一次(以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出“This puzzle has no final configuration.”

#include<stdio.h>
#include<windows.h>

int main()
{
	char mi[5][6] = { "TRGSJ","XDOKI","M VLN","WPABE","UQHCF" };
	int x, m = 2, n = 1;
	for (x = 0; x < 5; x++)
		printf("%s\n", mi[x]);
	char s, t, c;
	while (1)
	{
		scanf("%c", &s);
		getchar();
		if (s == '0')break;
		system("cls");
		switch (s)
		{
		case('w'):
			if (m - 1 < 0 || m - 1 > 4 || n < 0 || n > 4)
				printf("You can't move like this\n");
			else
			{
				t = mi[m][n];
				mi[m][n] = mi[m - 1][n];
				mi[m - 1][n] = t;
				m -= 1;
			}
			break;
		case('a'):
			if (m < 0 || m > 4 || n - 1 < 0 || n - 1 > 4)
				printf("You can't move like this\n");
			else
			{
				t = mi[m][n];
				mi[m][n] = mi[m][n - 1];
				mi[m][n - 1] = t;
				n -= 1;
			}
			break;
		case('s'):
			if (m + 1 < 0 || m + 1 > 4 || n < 0 || n > 4)
				printf("You can't move like this\n");
			else
			{
				t = mi[m][n];
				mi[m][n] = mi[m + 1][n];
				mi[m + 1][n] = t;
				m += 1;
			}
			break;
		case('d'):
			if (m < 0 || m > 4 || n + 1 < 0 || n + 1 > 4)
				printf("You can't move like this\n");
			else
			{
				t = mi[m][n];
				mi[m][n] = mi[m][n + 1];
				mi[m][n + 1] = t;
				n += 1;
			}
			break;
		default:
			printf("This is not a correct input!\n");
			break;
		}
		for (x = 0; x < 5; x++)
			printf("%s\n", mi[x]);
	}
	return 0;
}

是一个相对简单但是很有意思的题目,可以稍作改良,变成一个简单的推箱子小游戏

纵横字谜的答案

输入一个r行c列(1≤r,c≤10)的网格,黑格用“*”表示,每个白格都填有一个字母。如 果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边 界),则称这个白格是一个起始格。 

#include<stdio.h>

int main()
{
    char a[6][7];
 //定义字符串的时候要留出'\0'
    int  i, m, n;
    for (i = 0; i < 6; i++)
    {
        scanf("%s", a[i]);
    }
    printf("\n");
    for (m = 0; m < 6; m++)
    {
        for (n = 0; n < 6; n++)
        {
            if (a[m][n] == '*' && n == 0)
            {
                while (n < 6)
                {
                    ++n;
                    if (a[m][n] == '*');
                    else
                        break;
                }
            }
            if (a[m][n] == '*' && n != 0)
                while (n < 6)
                {
                    if (a[m][n] != '*')
                    {
                        printf("\n");
                        n--;
                        break;
                    }
                    else
                        n++;
                }
            else if (a[m][n] != '*')
                printf("%c", a[m][n]);
        }
        printf("\n");
    }
    printf("\n");
    for (n = 0; n < 6; n++)
    {
        for (m = 0; m < 6; m++)
        {
            if (a[m][n] == '*' && m == 0)
            {
                while (m < 6)
                {
                    ++m;
                    if (a[m][n] == '*');
                    else
                        break;
                }
            }
            if (a[m][n] == '*' && m != 0)
                while (m < 6)
                {
                    if (a[m][n] != '*')
                    {
                        printf("\n");
                        m--;
                        break;
                    }
                    else
                        m++;
                }
            else if (a[m][n] != '*')
                printf("%c", a[m][n]);
        }
        printf("\n");
    }
}

 这题就实现而言不算难,但是很难一次性作对,主要在于细节的把控

特别困的学生

课堂上有n个学生(n≤10)。每个学生都有一个“睡眠-清醒”周期,其中第i个学生醒Ai分 钟后睡Bi分钟,然后重复(1≤Ai,Bi≤5),初始时第i个学生处在他的周期的第Ci分钟。每个 学生在临睡前会察看全班睡觉人数是否严格大于清醒人数,只有这个条件满足时才睡觉,否 则就坚持听课Ai分钟后再次检查这个条件。问经过多长时间后全班都清醒。如果用(A,B,C)描 述一些学生,则图4-11中描述了3个学生(2,4,1)、(1,5,2)和(1,4,3)在每个时刻的行为。 

#include<stdio.h>

int mixt(int, int);
void firstcheck(int[10][3], int, int*, int*);
int check(int[10][3], int);
void recheck(int[10][3], int);

int main()
{
	int t = 1, n = 1, x[10][3] = {0}, a, no, t1, q, e;
	printf("请输入课堂上有多少学生-> ");
	no = scanf("%d", &n);
	a = n;
	for (; n > 0; n--)
	{
		no = scanf("%d %d %d", &x[a - n][0], &x[a - n][1], &x[a - n][2]);
		t1 = t;
		t = t1 * (x[a - n][0] + x[a - n][1]) / mixt(t, x[a - n][0] + x[a - n][1]);
	}
	t1 = t;
	while (t--)
	{
		q = 0, e = 0;
		firstcheck(x, 0, &q, &e);
		if (q >= e)
			recheck(x, 0);
		no = check(x, 0);
		if (no)
		{
			printf("经过 %d 分钟后,所有学生都清醒\n", t1 - 1 - t);
			return 0;
		}
	}
	printf("不存在所有学生清醒的状态\n");
	return 0;
}

int mixt(int a, int b)
{
	int c;
	while (c = a % b)
	{
		a = b;
		b = c;
	}
	return b;
}

void firstcheck(int x[10][3], int n, int* q, int* e)
{
	if (n == 10)
		return;
	if (x[n][0])
	{
		firstcheck(x, n + 1, q, e);
	}
	else
		return;
	if (x[n][2] <= x[n][0])
	{
		(*q)++;
	}
	else
	{
		(*e)++;
	}
		return;
}

void recheck(int x[10][3], int n)
{
	if (n == 10)
		return;
	if (x[n][0])
	{
		recheck(x, n + 1);
	}
	else
		return;
	if (x[n][2] == x[n][0])
		x[n][2] = 0;
	return;
}

int check(int x[10][3], int n)
{
	if (n == 10)
		return 1;
	int no = 0;
	if (x[n][0])
	{
		no = check(x, n + 1);
	}
	else
		return 1;
	if (x[n][2] <= x[n][0] && no == 1)
	{

		if (x[n][0] + x[n][1] == x[n][2])
			x[n][2] = 1;
		else
			x[n][2]++;
		return 1;
	}
	else
	{
		if (x[n][0] + x[n][1] == x[n][2])
			x[n][2] = 1;
		else
			x[n][2]++;
		return 0;
	}
}

已经算是比较久之前写的了,也许用不了这么多,但是当时作者也很菜,现在也懒得再写一遍了哈哈哈哈哈哈! 

洪水!

有一个n*m(1≤m,n<30)的网格,每个格子是边长10米的正方形,网格四周是无限大 的墙壁。输入每个格子的海拔高度,以及网格内雨水的总体积,输出水位的海拔高度以及有 多少百分比的区域有水(即高度严格小于水平面)

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

float j[900] = { 0 };

int cmy(const void*a, const void*b);

int main()
{
	int no, s = 0, x, y, i, n;
	float v, v1, k = 0;
	printf("请输入矩阵的长、宽->");
	no = scanf("%d %d", &x, &y);
	i = x * y;
	while (i--)
	{
		printf("请依次输入矩阵各网格的海拔高度->");
		no = scanf("%f", &j[s++]);
	}
	qsort(j, x * y, sizeof(float), cmy);
	float* a, * b;
	a = j;
	b = j;
	printf("请输入矩阵内水的总体积->");
	no = scanf("%f", &v);
	while (v != 0.0)
	{
		a = b;
		while ((*b) == (*a))
		{
			if (b == &j[x * y - 1])
				break;
			b++;
		}
		if ((*a) == (*b))
		{
			for (i = 0; i < x * y; i++)
				j[i] += v / (x * y);
			break;
		}
		else
		{
			n = (b - j);
			v1 = (*b) - (j[0]);
			if (v >= v1 * n)
			{
				k = b - j;
				a = j;
				while (a != b)
				{
					(*a) = (*b);
					a++;
				}
				v -= (v1 * n);
				if (v != 0)
					k = 0;
			}
			else
			{
				a = j;
				while (a != b)
				{
					(*a) += v / n;
					a++;
				}
				v = 0.0;
			}

		}
	}
	printf("\n最终水平面海拔为 %f \n", j[0]);
	n = 0;
	for (i = 0; i < x * y; i++)
	{
		if (j[i] > j[0])
			n++;
	}
	printf("有 %.2f%% 的区域在水平面之下\n", (100 * k) / (x * y));
	printf("有 %d 块区域在水平面之上\n\n", n);
	return 0;
}

int cmy(const void* a, const void* b)
{
	if ((*(float*)a) > (*(float*)b))
		return 1;
	else if ((*(float*)a) < (*(float*)b))
		return -1;
	else
		return 0;
}

qsort这个函数经常用到,也许挺多人看到一种看似比较简单的写法,直接return 两个数相减的值,对于大部分情况而言都是可以的,但是需要考虑到如果是对浮点型数组排序,那么该如何反悔呢?假定强转为int类型,那么就会出现取整的情况,假定强转为float类型,那么不符合cmy函数的返回类型(cmy函数在qsort里面要求返回整形),所以建议所以的cmy函数都写成如上的三个return

 综合

在此记录一些曾经写过的比较有意思的题目,稍微比较考验综合能力吧!

由于大部分的代码都比较长,所以作者一般另写一篇博客来讲一题,或者提供相应的git网址.

扫雷(可连续展开)

黑框版本的扫雷游戏,相信在b站看过鹏哥视频的都不陌生哈哈哈哈哈!

扫雷——可连续展开空白部分

象棋(判断残局)

考虑一个象棋残局,其中红方有n(2≤n≤7)个棋子,黑方只有一个将。红方除了有一个 帅(G)之外还有3种可能的棋子:车(R),马(H),炮(C),并且需要考虑“蹩马 腿”,且将和帅不能照面的规则。 输入所有棋子的位置,保证局面合法并且红方已经将军。你的任务是判断红方是否已经把黑方将死。

判断象棋残局

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值