6 条题解

  • 2
    @ 2022-11-2 11:08:26

    通读题目后,不难发现:如果买完奖品A与B后钱数还有剩余,可买奖品C“填补”剩余钱数直到钱花完(因为奖品C单价为1元),之后再判断总量是否大于30即可。因此,只需枚举奖品A与奖品B的数量即可(双重for循环)主要代码如下:

    /*
    i为奖品A数量
    j为奖品B数量
    k为奖品C数量
    sum为总方案数
    */
    for (int i = 1 ; i <= n / a ; i++)
    {
        for (int j = 1 ; j <= n / b ; j++)
        {
            int k = n - (i * a + j * b);
            if (a * i + b * j < n && i + j + k > 30)
            {
                sum++;
            }
        }
    }
    
    • 1
      @ 2022-10-27 13:36:09

      就喜欢van一van高级代码()
      DFS深度优先搜索算法解题

      #include<bits/stdc++.h>
      using namespace std;
      int n,a,b,total; // total为方案数
      /*
       * kind  --- 种类
       * num   --- 物品总数
       * money --- 剩余金钱
       */
      void dfs(int kind,int num,int money){
          if(kind>3){ // 已经买齐3种物品
              if(num>30&&money==0)total++; // 满足题目条件时
              return; // 返回
          }
          if(money<=0)return; // 剪枝优化:金钱小于等于0且未买齐3种物品说明不必再往后搜索
          // 按照种类进行搜索
          if(kind==1)
              for(int i=1;i<=money/a;i++) // 尝试所有物品都买A
                  dfs(2,num+i,money-a*i);
          else if(kind==2)
              for(int i=1;i<=money/b;i++) // 尝试所有物品都买B
                  dfs(3,num+i,money-b*i);
          else if(kind==3)
              for(int i=1;i<=money;i++) // 尝试所有物品都买C
                  dfs(4,num+i,money-i);
      }
      int main(){
          cin>>n>>a>>b;
          dfs(1,0,n);
          cout<<total;
          return 0;
      }
      
      • 0
        @ 2024-4-21 8:37:31
        #include<bits/stdc++.h>
        using namespace std;
        int n,a,b,s;
        int main(){
        	cin>>n>>a>>b;
        	for(int i=1;i<=1111;i++){
        		for(int j=1;j<=1111;j++){
        			if(a*i+b*j<n && i+j+(n-i*a-b*j)>30){
        				s++;
        			}
        		}
        	}
        	cout<<s;
        }
        
        • 0
          @ 2022-8-1 19:25:27

          一道只需要三重循环枚举就能AC的题目。 第一重循环枚举购买奖品 AA 的个数。因为只有 nn 元钱,而奖品 AA 的单价是 aa 元所以至多能买到 n/an/a 个奖品 AA ,同理,至多能买到 n/bn/b 个奖品 BBnn 个奖品 CC 。 最后只需要用三个循环变量 iijjkk 来枚举三个奖品个分别要买多少个就行了。注意:最后还要条件判断一下此方案是否满足题目要求,即这些奖品总数要超过 3030 个,并且每种奖品至少买一个,这 nn 元钱必须全部花完,如满足就将方案数加 11

          代码1:

          #include <cstdio>//1.0版代码
          using namespace std;
          int n,a,b,ans;
          int main()
          {
              scanf("%d%d%d",&n,&a,&b);//可替换为cin>>n>>a>>b;
              for(int i=1;i<=n/a;i++)//枚举购买奖品A个数
                  for(int j=1;j<=n/b;j++)//枚举购买奖品B个数
                      for(int k=1;k<=n;k++)//枚举购买奖品C个数
                          if(i*a+j*b+k==n&&i+j+k>30)//判断是否满足题意
                              ans++;//如满足,方案数加1
              printf("%d\n",ans);//输出,可替换为cout<<ans<<endl;
              return 0;
          }
          

          仔细观察,可以发现,这个程序的时间复杂度是可以被优化的。设买了 ii 个奖品 AAjj 个奖品 BBkk 个奖品 CC , 当买完奖品 AA 后,只剩下 nian-i*a 元钱去买奖品 BB 和奖品 CC 。我们此时会发现,剩下的钱至多能买 (nia)/b(n-i*a)/b 个奖品 BB 。同样的,买完奖品 AA 和奖品 BB 后,只会剩下 niajbn-i*a-j*b 元钱去买奖品 CC ,剩下的钱至多能买 niajbn-i*a-j*b 个奖品 CC 。所以,循环变量 jj 只需循环到 (nia)/b(n-i*a)/b ,循环变量 kk 只需循环到 niajbn-i*a-j*b

          代码2:

          #include <cstdio>//2.0版代码
          using namespace std;
          int n,a,b,ans;
          int main()
          {
              scanf("%d%d%d",&n,&a,&b);
              for(int i=1;i<=n/a;i++)//枚举购买奖品A个数
                  for(int j=1;j<=(n-i*a)/b;j++)//枚举购买奖品B个数,优化后的代码
                      for(int k=1;k<=(n-i*a-j*b);k++)//枚举购买奖品C个数,优化后的代码
                          if(i*a+j*b+k==n&&i+j+k>30)
                              ans++;
              printf("%d\n",ans);
              return 0;
          }
          

          其实,这个代码还可以再次被优化。因为题目中已经明确地指出了“这 nn 元钱必须全部花完”,所以实际上第三重循环可以被省去。

          代码3:

          #include <cstdio>//3.0版代码
          using namespace std;
          int n,a,b,ans;
          int main()
          {
              scanf("%d%d%d",&n,&a,&b);
              for(int i=1;i<=n/a;i++)//枚举购买奖品A个数
                  for(int j=1;j<=(n-i*a)/b;j++)//枚举购买奖品B个数
                  {
                      int k=n-i*a-j*b;//购买奖品C的个数
                      if(k>0&&i+j+k>30)//这里要条件判断一下购买奖品C的个数是否不为0
                          ans++;
                  }
              printf("%d\n",ans);
              return 0;
          }
          
          • 0
            @ 2021-8-24 13:29:49

            看到同学们的题解都写的不错,不过题解的代码格式还得注意一下,可以去讨论区看一下我写的关于题解。

            这个题的话就是一个很经典的枚举问题,不过要注意数据范围,确实是有些没必要的循环就不要进行了~

            代码如下:

            #include <bits/stdc++.h>
            using namespace std;
            
            int n, a, b, c, k, sum;
            
            int main() {
                cin >> n >> a >> b;
            
                for (int i = 1; i <= n / a; i++) {
                    for (int j = 1; j <= n / b; j++) {
                        k = n - i * a - j * b;
            
                        if ((i + j + k > 30) && (k >= 1)) {
                            sum++;
                        }
                    }
                }
            
                cout << sum;
                return 0;
            }
            
            • 0
              @ 2021-8-23 15:14:37

              这次用的是枚举算法,肯定要用的是三层循环嵌套,但是会超时。给个提示:叮叮老师说过不要进行不必要的循环。如果i到了一定数量就break,还有一些坑需要注意一下,比如说如果价格到了n而且礼品数量>30(不是≥30)ans在加1

              • 1

              信息

              ID
              1224
              时间
              1000ms
              内存
              256MiB
              难度
              4
              标签
              递交数
              250
              已通过
              107
              上传者