鱼C论坛

 找回密码
 立即注册
查看: 1438|回复: 6

[已解决]三 连 击 问题

[复制链接]
发表于 2022-6-5 22:17:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
题目 https://www.luogu.com.cn/problem/P1008
我的代码如下 , 思路是先枚举出一个最小的 , 然后再看第二个第三个是否可行
但是它报错了 , 检查不出来。。。
  1. #include <bits/stdc++.h>
  2. using namespace std;

  3. bool vis[9] = {1};

  4. bool isavaliable(int num, bool & vis[9]){
  5.         memset(vis, 1, sizeof(vis));
  6.         int nx2 = num * 2;
  7.         int nx3 = num * 3;
  8.         for(int i = 0; i < 3; i++){
  9.                 if(vis[nx2%10]) vis[nx2%10] = 0;
  10.                 else return 0;
  11.                 if(vis[nx3%10]) vis[nx3%10] = 0;
  12.                 else return 0;
  13.                 nx2 /= 10;
  14.                 nx3 /= 10;
  15.         }
  16.         return 1;
  17. }

  18. int main(){
  19.         ios::sync_with_stdio(0);
  20.         
  21.         for(int i = 1; i < 4; i++){ // 可以证明最小的百位数字为 1, 2, 3 不然就超了
  22.                 for(int j = 1; j < 10; j++){
  23.                         if(i == j) continue;
  24.                         for(int k = 1; k < 10; k++){
  25.                                 if(i == k || j == k) continue;
  26.                                 int num = i * 100 + j * 10 + k;
  27.                                 if(isavaliable(num, vis)) cout << num << ' ' << num * 2 << ' ' << num * 3 << endl;
  28.                         }
  29.                 }
  30.         }

  31.         return 0;
  32. }
复制代码
最佳答案
2022-6-5 23:45:44
本帖最后由 傻眼貓咪 于 2022-6-5 23:48 编辑

我的思路:
题目提示:
(一)1:2:3 的比例分组
(二)三位数

所以答案必然在 100 至 999 之间,而且最大数的比例是最小数的三倍,那么最小数必然小于 999 / 3(因为要分成三等份)
以上提示可以得出,最小数在 123 ~ 999/3 之间(循环次数大大降低至 210 次)
接下来把最小数分成三个三位数,如:最小数、最小数*2,最小数*3
然后再判断是否三个三位数所有数字没有重复即可。
  1. #include <iostream>
  2. #include <vector>
  3. #include <map>

  4. using std::vector;
  5. vector<int> digit(int num) {
  6.     vector<int> res;
  7.     res.push_back(num / 100);
  8.     res.push_back((num / 10) % 10);
  9.     res.push_back(num % 10);
  10.     return res;
  11. }

  12. using std::map;
  13. using std::cout, std::endl;
  14. void check(int a, int b, int c) {
  15.     map<int, bool> numbers;
  16.     for (int n = 1; n < 10; ++n) numbers[n] = true;
  17.     vector<int> A = digit(a); // 第一个三位数
  18.     vector<int> B = digit(b); // 第二个三位数
  19.     vector<int> C = digit(c); // 第三个三位数
  20.     for (int i = 0; i < 3; ++i) {
  21.         if (not A[i] or not B[i] or not C[i]) return;
  22.         numbers[A[i]] = false;
  23.         numbers[B[i]] = false;
  24.         numbers[C[i]] = false;
  25.     }
  26.     for (auto [key, value] : numbers) {
  27.         if (value) {
  28.             return;
  29.         }
  30.     }
  31.     cout << a << " " << b << " " << c << endl;
  32. }

  33. int main(void) {
  34.     for (int num = 123; num < 999 / 3; ++num) {
  35.         check(num, num * 2, num * 3);
  36.     }
  37.     return 0;
  38. }
复制代码
  1. 192 384 576
  2. 219 438 657
  3. 273 546 819
  4. 327 654 981
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-6-5 23:25:57 | 显示全部楼层
先给个建议:vis是全局变量,所以不需要作为函数的参数,也可以在函数中访问此变量。

或者报错有没有可能是因为 两个变量重名?

还要加一个 num3 是否为 3 位数的判断

函数中 nx2 % 10 要减 1
而且你没有对num 的查重判断(也就是初始数)

我写了一个代码,洛谷通过了:
  1. #include <iostream>

  2. bool isNumberUsed[9];
  3. bool ifAvaliable(int num)
  4. {
  5.         for (size_t i = 0; i < 9; i++)
  6.         {
  7.                 isNumberUsed[i] = false;
  8.         }

  9.         int num1 = num;
  10.         int num2 = num * 2;
  11.         int num3 = num * 3;

  12.         if (num3 >= 1000) return false;

  13.         for (size_t i = 0; i < 3; i++)
  14.         {
  15.                 if (!isNumberUsed[num1 % 10 - 1]) isNumberUsed[num1 % 10 - 1] = true;
  16.                 else return false;

  17.                 if (!isNumberUsed[num2 % 10 - 1]) isNumberUsed[num2 % 10 - 1] = true;
  18.                 else return false;

  19.                 if (!isNumberUsed[num3 % 10 - 1]) isNumberUsed[num3 % 10 - 1] = true;
  20.                 else return false;

  21.                 num1 /= 10;  num2 /= 10; num3 /= 10;
  22.         }

  23.         return true;
  24. }



  25. int main()
  26. {
  27.         for (size_t i = 1; i <= 3; i++)
  28.         {
  29.                 for (size_t j = 1; j <= 9; j++)
  30.                 {
  31.                         if (i == j) continue;

  32.                         for (size_t k = 1; k <= 9; k++)
  33.                         {
  34.                                 if (i == k || k == j) continue;

  35.                                 int num = i * 100 + j * 10 + k;

  36.                                 if (ifAvaliable(num)) std::cout << num << ' ' << num * 2 << ' ' << num * 3 << std::endl;
  37.                         }
  38.                 }
  39.         }

  40.         return 0;
  41. }
复制代码


评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
柿子饼同学 + 5 + 5

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2022-6-5 23:30:28 | 显示全部楼层
这应该是我第一次写这么长的回答
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-6-5 23:45:44 | 显示全部楼层    本楼为最佳答案   
本帖最后由 傻眼貓咪 于 2022-6-5 23:48 编辑

我的思路:
题目提示:
(一)1:2:3 的比例分组
(二)三位数

所以答案必然在 100 至 999 之间,而且最大数的比例是最小数的三倍,那么最小数必然小于 999 / 3(因为要分成三等份)
以上提示可以得出,最小数在 123 ~ 999/3 之间(循环次数大大降低至 210 次)
接下来把最小数分成三个三位数,如:最小数、最小数*2,最小数*3
然后再判断是否三个三位数所有数字没有重复即可。
  1. #include <iostream>
  2. #include <vector>
  3. #include <map>

  4. using std::vector;
  5. vector<int> digit(int num) {
  6.     vector<int> res;
  7.     res.push_back(num / 100);
  8.     res.push_back((num / 10) % 10);
  9.     res.push_back(num % 10);
  10.     return res;
  11. }

  12. using std::map;
  13. using std::cout, std::endl;
  14. void check(int a, int b, int c) {
  15.     map<int, bool> numbers;
  16.     for (int n = 1; n < 10; ++n) numbers[n] = true;
  17.     vector<int> A = digit(a); // 第一个三位数
  18.     vector<int> B = digit(b); // 第二个三位数
  19.     vector<int> C = digit(c); // 第三个三位数
  20.     for (int i = 0; i < 3; ++i) {
  21.         if (not A[i] or not B[i] or not C[i]) return;
  22.         numbers[A[i]] = false;
  23.         numbers[B[i]] = false;
  24.         numbers[C[i]] = false;
  25.     }
  26.     for (auto [key, value] : numbers) {
  27.         if (value) {
  28.             return;
  29.         }
  30.     }
  31.     cout << a << " " << b << " " << c << endl;
  32. }

  33. int main(void) {
  34.     for (int num = 123; num < 999 / 3; ++num) {
  35.         check(num, num * 2, num * 3);
  36.     }
  37.     return 0;
  38. }
复制代码
  1. 192 384 576
  2. 219 438 657
  3. 273 546 819
  4. 327 654 981
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-6-6 15:09:23 | 显示全部楼层
本帖最后由 jhq999 于 2022-6-6 15:18 编辑
  1. #include <bits/stdc++.h>
  2. using namespace std;



  3. bool isavaliable(int num){
  4.         int i,j,k;
  5.         int vis=1;
  6.         i=num/100,j=(num/10)%10,k=num%10;
  7.         vis|=1<<i,vis|=1<<j,vis|=1<<k;
  8.         num/=3;
  9.         i=num/100,j=(num/10)%10,k=num%10;
  10.          vis|=1<<i,vis|=1<<j,vis|=1<<k;
  11.          num<<=1;
  12.          i=num/100,j=(num/10)%10,k=num%10;
  13.          vis|=1<<i,vis|=1<<j,vis|=1<<k;
  14.         return (vis==1023);
  15. }

  16. int main(){
  17.         ios::sync_with_stdio(0);
  18.         int count=0,i,j,k,num;
  19.         for(num=987;num>=369;num--)
  20.         {
  21.             if(num%3||0==num%10||0==(num/10)%10)continue;
  22.             count+=1;

  23.             if(isavaliable(num))
  24.             {
  25.                cout<<(num/3)<<' ';
  26.                cout<<((num/3)<<1)<<' '<<num<<endl;
  27.             }

  28.         }
  29.         cout<<count<<endl;



  30.         return 0;
  31. }
复制代码
  1. #include <bits/stdc++.h>
  2. using namespace std;



  3. bool isavaliable(int num){
  4.         int i,j,k;
  5.         int vis=1;
  6.         i=num/100,j=(num/10)%10,k=num%10;
  7.         vis|=1<<i,vis|=1<<j,vis|=1<<k;
  8.         num>>=1;
  9.         i=num/100,j=(num/10)%10,k=num%10;
  10.          vis|=1<<i,vis|=1<<j,vis|=1<<k;
  11.          num*=3;
  12.          i=num/100,j=(num/10)%10,k=num%10;
  13.          vis|=1<<i,vis|=1<<j,vis|=1<<k;
  14.         return (vis==1023);
  15. }

  16. int main(){
  17.         ios::sync_with_stdio(0);
  18.         int count=0,i,j,k,num;
  19.         for(num=246;num<=658;num++)
  20.         {
  21.             if(num%2||0==num%10||0==(num/10)%10)continue;
  22.             count+=1;

  23.             if(isavaliable(num))
  24.             {
  25.                cout<<(num>>1)<<' ';
  26.                cout<<num<<' '<<((num>>1)*3)<<endl;
  27.             }

  28.         }
  29.         cout<<count<<endl;



  30.         return 0;
  31. }
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
柿子饼同学 + 5 + 5

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-6-11 16:11:54 | 显示全部楼层
本帖最后由 柿子饼同学 于 2022-6-11 16:14 编辑
liuzhengyuan 发表于 2022-6-5 23:25
先给个建议:vis是全局变量,所以不需要作为函数的参数,也可以在函数中访问此变量。

或者报错有没有可 ...


谢谢~
话说 , 函数里改变全局变量只是在函数里改变吧
后面就改不了了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-6-11 16:14:11 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-20 11:33

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表