一道题加深对遍历的理解(多重for循环如何写)
一道题加深对遍历的理解(多重for循环如何写)
题目:
`期末考试有三种题型,选择题,每题2.3分,填空题,每题3.4分,编程题,每题12分。
张小元一共做出了n道题,最终的得分是m,问张小元做出了选择题,填空题和编程题各几道。如无解,输出Error!
输入:做出的总题数n,最终得分m
输出:依次输出编程题,填空题和选择题的数目,如果有多组结果满足条件,则依次按照编程题的数目,填空题的数目和选择题的数目降序输出。`
分析:
这是一道较为简单的遍历题,但如何写得效率一点,好看一点呢?以前没细想郭这个问题,现在来分析一下;
-
假如我们喜欢暴力枚举,而且枚举时也不喜欢考虑任何问题,那么我们甚至可以写成这样:
void demo2() { int n, m; scanf("%d%d", &n, &m); char flag = 0; for (int i = n; i >= 0; i--) { for (int j = 0; j <= n; j++) { for (int k = 0; k <= n; k++) { if (i + j + k == n) { if (fabs(i * 2.3 + j * 3.4 + k * 12 - m) < 1e-4) { printf("%d %d %d\n", k, j, i); flag++; } } } } } if (!flag) { printf("Error!\n"); } } int main() { demo2(); }
这个用例就是相当于把一个
n*n*n
空间的所有点先找出来,然后再去对他做约束,但其实在数学中我们知道如果知道约束了,我们可以忽略约束之外的那部分点,直接在约束之内找:很遗憾,出题者不允许这种浪费,于是专门设了过不了的一个用例:
-
假如我们知道了可以利用多重积分的概念来约束上下限,那么这样我们的程序就会变得高效、美观很多;
#include<stdio.h> #include<math.h> void demo1(){ int n,m; scanf("%d%d",&n,&m); char flag=0; for(int i=n;i>=0;i--){ for(int j=0;i+j<=n;j++){ int k=n-i-j; if(fabs(i*2.3+j*3.4+k*12-m)<1e-4){ printf("%d %d %d\n",k,j,i); flag++; } } } if(!flag){ printf("Error!\n"); } } int main(){ demo1(); }
-
在上面我们也发现了很美观的事实,通常我们都是顺序遍历,但恰好这道题要求的是逆序输出,很简单的,我们将
i
的遍历从0
到n
改为从n
到0
,而对j
的上下限约束,我们好像就是通过数学中的二重积分一样给它划好了上下限(但其实更有利的地方程序中可以直接把上下限写成一个判断的语句,这样就更加有利了我们的积分操作了),这样的话我们就节省了很多不必要的运行次数。(就过了)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人