本文是根据博主安然无虞的文章进行我的思维训练和练习,下面是我的练习代码和思路。
1.换酒问题
#include<stdio.h>
int main()
{
int numExchange,numBottles;
int k;
scanf("%d %d",&numBottles,&numExchange);
k=numBottles;
while(k/numExchange>=1)
{
k=k/numExchange;
numBottles+=k;
}
printf("%d",numBottles);
return 0;
}
思路:
这里设置三个变量:numExchange——需要空瓶数,numBottles——一共的酒数,k——空瓶;一开始,让k=numBottles;然后k/numExchange-这是第二次的酒瓶,在加到numBottles上,对k/numExchange进行循环即可
2. 按奇偶排序数组
#include <stdio.h>
int main()
{
int num[100],n,target[100]={0},i=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
for(int j=0;j<n;j++)
{
if(num[j]%2!=0)
target[i++]=num[j];
}
for(int j=0;j<n;j++)
{
if(num[j]%2==0)
target[i++]=num[j];
}
for(int i=0;i<n;i++)
printf("%d ",target[i]);
return 0;
}
思路:
这里我设置了两个数组,一个目标数组,一个结果数组,将每次排列的结果放到结果数组里,这样原数组的值就不会被覆盖,先对所有奇数排列,在对所有偶数排列就能得到结果。
3.害死人不偿命的(3n+1)猜想
#include <stdio.h>
int fun(int n)
{
static int k=0;
if(n%2==0)
{
n=n/2;
k++;
return fun(n);
}
else if(n%2!=0&&n!=1)
{
n=(3*n+1)/2;
k++;
return fun(n);
}
else if(n==1)
return k;
}
int main()
{
int n,k;
scanf("%d",&n);
k=fun(n);
printf("%d",k);
}
思路;
这里我采用了递归的方式来解题,将n传递进去,进行变换,当n==1时即为出口,注意fun里面的k要设为static,不然每次进行递归k都会初始化为0
4.挖掘机技术哪家强
#include<stdio.h>
#define MAXN 100010
int school[MAXN] = { 0 };//记录每个学校的总分
int main()
{
int n = 0;
int schID = 0;//学校编号
int score = 0;//分数
scanf("%d", &n);//参赛人数
for (int i = 0; i < n; i++)//读入每一位参赛人员信息
{
scanf("%d %d", &schID, &score);
school[schID] += score;//学校schID的总分增加score
}
int k = 0;//用于记录最高总分的学校编号
int max = -1;//用于记录最高总分
for (int i = 1; i <= n; i++)//由于学校是从1开始连续编号的,所以范围是1~N,其中包括N
{
if (school[i] > max)
{
max = school[i];
k = i;
}
}
printf("%d %d\n", k, max);
return 0;
}
思路:
这里我刚开始的想法是定义一个数组,进行循环,当编号相同就相加,但是实现过程太麻烦了。
这题博主的做法我学习到了,将编号作为数组的下标,这样输入一个相同的编号就能直接加到数组里面。然后在使用打擂台的方式找到最高的分数和学校,实现方法简单,方法非常好。
5.找X
#include <stdio.h>
int main()
{
int n,x;
int num[200];
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
scanf("%d",&x);
for(int i=0;i<n;i++)
{
if(x==num[i])
{
printf("%d",i);
break;
}
}
}
思路:
这就是个很简单的输入,遍历之后输出就可以了。
6.图形输出
#include <stdio.h>
int main()
{
int n;
int i=0,j=0,k=0;
char c,s[21][21];
scanf("%d %c",&n,&c);
if(n%2==0)
k=n/2;
else
k=n/2+1;
for(i=0;i<k;i++)
{
for(j=0;j<n;j++)
{
s[i][j]=c;
if(i==0||i==k-1||j==0||j==n-1)
printf("%c",s[i][j]);
else
printf(" ",s[i][j]);
}
putchar('\n');
}
return 0;
}
思路:
这种图行输出都是要看规律的,i——行,j——列,看每一行和每一列有什么规律,这里第一行最后一行,第一列最后一列都是字符,按照这个规律输出,其他行和列输出空格即可
7. 日期差值
#include<stdio.h>
//#include<stdbool.h>
//平年和闰年每个月的天数
//之所以将一维写成13,是因为保证二维数组的下标与我们生活中的月份相对应,方便处理
int month[13][2] = { {0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31} };
bool isLeap(int year)
{
return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}
int main()
{
int time1, y1, m1, d1;
int time2, y2, m2, d2;
scanf("%d %d", &time1, &time2);
if (time1 > time2)//设定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;//记录结果,之所以初始值为1,为了满足“当两个日期是连续的,规定它们之间的天数是2天”这个条件
//第一个日期没有达到第二个日期时进行循环
//即!((y1 == y2)&&(m1 == m2)&&(d1 == d2))
while (y1 < y2 || m1 < m2 || d1 < d2)
{
d1++;//天数加1
if (d1 == month[m1][isLeap(y1)] + 1)//满当月天数
{
m1++;//日期变成下个月的1号
d1 = 1;
}
if (m1 == 13)//月份满12个月
{
y1++;//日期变成下一年的1月
m1 = 1;
}
ans++;//累计
}
printf("%d\n", ans);//输出结果
}
思路:
这题我写的时候没有考虑这么周全,后面看博主的代码认真理解,将思路做法记录。
1.定义一个二维数组,一维13对应了一年的十二天,二维的分别代表平年的闰年;第一维记录平年的天数,第二年记录闰年的天数(这里的主要差别是2月份的天数)。
2.将年份进行判断是平年还是闰年,得到的结果作为数组的二维下标。
3.将输入的数值进行拆分为年,月,日。
4.将ans设置为1,然后对时间短的年,月,日进行递加,直至和另一个相等,即可求得时间差。
8.D进制的A+B
#include <stdio.h>
#include <math.h>
int main()
{
int a,b,c=0,d,k,n=0;
int num[10];
scanf("%d %d %d",&a,&b,&d);
c=a+b;
while(c/d>=0)
{
num[n]=c%d;
c=c/d;
if(c==0)
break;
n++;
}
for(n;n>=0;n--)
printf("%d",num[n]);
return 0;
}
思路:
9.回文串
#include <stdio.h>
#include <string.h>
int main()
{
int k;
char str[255];
scanf("%s",&str);
k=strlen(str);
for(int i=0;i<=k/2;i++)
{
if(str[i]!=str[k-i-1])
{
printf("NO\n");
break;
}
else
k=1;
}
if(k==1)
printf("YES\n");
return 0;
}
思路:
遍历循环,一但发现不对称就输出NO,跳出循环,如果是回文在输出YES
10.说反话
#include<stdio.h>
int main()
{
int num = 0;
char ans[90][90] = { 0 };
while (scanf("%s", ans[num]) != EOF)//想想为什么不要&
num++;
for (int i = num - 1; i >= 0; i--)//倒着输出单词
{
printf("%s", ans[i]);
if (i > 0)//注意这个条件
printf(" ");
}
return 0;
}
思路:
这题我刚开始只是将整个倒叙输出,结果发现它只是将单词单词从最后一个到第一个输出而已,这边结合博主代码进行了思考:
定义一个二维数组,,第一维是单词的个数,由于scanf输入遇到空格就会停止,这样每次输入就存到每一维度中,每一个一维数组又是个字符串(也就是单词),这样直接倒叙输出每一个一维数组里面的单词就可以实现了
while (scanf("%s", ans[num]) != EOF)
num++;