第一题.
1.问题:小蓝数字卡片题
小蓝有很多数字卡片,每张卡片上都是数字0到9。 小蓝准备用这些卡片来拼一些数,他想从1开始拼现在小蓝手里有0到9的卡片各2021张,共20210张,请问小蓝可以从1拼到多少?
2.解题过程:
(1).转化字符串法:
//法一
struct num { char a; int b; };
struct num x[10];//结构体数组用于存放数字和其卡片数量
int main()
{
char m[10] = { '0' };
int arr[10] = { 0 };
int a, b, c, d;
for (a = 0; a < 10; a++)//存放0`9
{
x[a].a = '0' + a;
}
for (a = 0; a < 10; a++)//存放卡牌数
{
x[a].b = 2021;
}
for (a = 1;; a++)
{
sprintf(m, "%d", a);//数字转化字符
b = strlen(m);
for (c = 0; c < b; c++)
{
for (d = 0; d < 10; d++)
{
if (x[d].b == 0)判断是否有一个数字卡牌用完,然后输出结束所有循环
{
goto h;
}
else
{
if (m[c] == x[d].a)//进行相应卡牌的减少
{
x[d].b--; break;
}
}
}
}
}h:printf("%d", a - 1);
return 0;
}
(2).直接(暴力求解)法
//法二
int arr[10];
void judge(int a)//进行卡片数量的加减
{
switch (a)
{
case 0:arr[0]--;
break;
case 1:arr[1]--;
break;
case 2:arr[2]--;
break;
case 3:arr[3]--;
break;
case 4:arr[4]--;
break;
case 5:arr[5]--;
break;
case 6:arr[6]--;
break;
case 7:arr[7]--;
break;
case 8:arr[8]--;
break;
case 9:arr[9]--;
break;
}
}
void part(int a)//计算其个位的数据是几
{
if (a < 10)
judge(a % 10);//返回judge函数进行相应的卡片加减
else
{
judge(a % 10);//将较大的数据利用递归返回其每一位的数据进入judge,进行相应的卡片加减
a = a / 10;
part(a);
}
}
int main()
{int a = 0;
for (a = 0;a<10; a++)//0~9个元素都存入2021使用一张减1;
{
arr[a] = 2021;
}
for (a = 0;; a++)
{
part(a);//主判断过程
for (int b = 0; b < 10; b++)
{
if (arr[b] == 0)//判断是否有一个数字卡牌用完,然后输出
{
printf("%d", a);
goto h;//结束所有循环
}
}
}h:
return 0;}
3.结果:
4.方法总结:
(1).法一关键点:利用结构体数组与sprintf函数
(2).法二关键点:利用递归,%的妙用
第二题.
1.问题:利用坐标确定直线。(暴力求解)
- 解题过程
struct sb { int a; int b; };
struct sb lqb[20 * 21];//1以上是构建数据放坐标
int l = 0;//提前吧平行x,y轴直线算上
int main()
{
int c = 0, k, b;
for (int a = 0; a < 20; a++)//每个元素内放上不同的坐标
{
for (int b = 0; b < 21; b++)
{
lqb[c].a = a;
lqb[c].b = b;
c += 1;
}
}
for (int a = 0; a < 420; a++)//
{
for (int b = 0; b < 420; b++)
{
if ((lqb[a].a != lqb[b].a) && (lqb[a].b != lqb[b].b))
{
l++;//l存放不同的直线
}
}
}l = l / 2;//除以二是因为排列组合没有顺序
printf("%d", l+20+21);
return 0;
}
- 结果
40257
第三题.
- 问题:回文日期
- 解题过程
int month2[13] = { 0,31,29,31,30,31,30,31,31,30,31,30,31 };//闰年
int month1[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//平年
int part2(int x)//判断是否为闰年
{
if ((x % 4 == 0 && x % 100 != 0) || (x % 400 == 0))
{
return 1;
}
else
{
return 0;
}
}
int judge(char *a)//此函数用于判断数据是否为合法日期
{
int h;
int arr[10] = { 0 };
for (int b = 0; b < 4; b++)
{
arr[b] = a[b] - '0';
}h = arr[3] * 1000 + arr[2] * 100 + arr[1] * 10 + arr[0];
if (part2(h))//根据年份不同,合法日期也是不同的
{
if ((arr[0] * 10 + arr[1]) <= 12)
{ if (month2[arr[0] * 10 + arr[1]] >= (arr[2] * 10 + arr[3]))
{return 1;}
else
{return 0;}
}
else
{
return 0;
}
}
else
{
if ((arr[0] * 10 + arr[1]) <= 12)
{
if (month1[arr[0] * 10 + arr[1]] >= (arr[2] * 10 + arr[3]))
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
int part(a)//数据反过来存放当作月日
{
char c='0';
char arr[10] = { '0' };
sprintf(arr,"%d",a );
for (int b = 0; b < 2; b++)
{
c = arr[b];
arr[b] = arr[3 - b];
arr[3 - b] = c;
}
if (judge(arr))//judge判断是否为合法日期
return 1;
else
return 0;
}
void part1(int a)//打印该回文日期
{
char arr[10] = { "0" };
sprintf(arr, "%d", a);
char c = '0';
for (int b = 0; b < 4; b++)
{
arr[7 - b] = arr[b];
}
for (int b = 0; b < 8; b++)
{
printf("%c", arr[b]);
}
}
int main()
{int y = 1;
int a = 1212;
scanf("%d", &a);//输入日期
a = a / 10000;//因为每年至多有一个回文日期所以直接算年然后看倒过来是否合法
p:
for (int b = 1;; b++)
{
a += 1;
if (part(a))//将数据反过来当作月日,再判断,为合法日期返回1,停止循环
break;
}
if (y == 1)
{
y--;
part1(a);//只打印一次普通回文日期;
}
else
;
char arr[10] = { "0" };
sprintf(arr, "%d", a);
if ((arr[0] == arr[2]) && (arr[1] == arr[3]))//判断是否为ababbaba型回文时期并输出
{ printf("\n");
part1(a);
}
else
goto p;//不是则返回到循环前继续循环
return 0;
}
- 结果