• 蓝桥杯刷题二


    6.费解的开关

    这题就是上一节的那题的扩展版了

    首先第一行的状态如果确定了 那么后面要进行的操作也是确定的 所以枚举一下第一行的状态就好了

    但是不同的是 上一题的第一个状态是确定的 但是这题的第一个状态不是确定的 因为可以通过按很多不同的按钮使得第一个的状态改变 而上一题只能有一个操作使得第一个状态的改变 所以这个还需要加一个二进制枚举一下第一行的状态 然后操作后面的按钮使得第一行全部变为符合要求的状态 再判断一下合法解

    1. #include
    2. using namespace std;
    3. const int N=6;
    4. char str[N][N],temp[N][N];
    5. int dx[6]={-1,0,1,0,0},dy[6]={0,1,0,-1,0};//上 右 下 左 中
    6. void trans(int x,int y)//用来改变一个位置
    7. {
    8. for(int i=0;i<5;i++)//枚举五个方向
    9. {
    10. int tx=x+dx[i],ty=y+dy[i];
    11. if(tx<0||tx>4||ty<0||ty>4) continue;
    12. temp[tx][ty]^=1;
    13. }
    14. }
    15. void solve()
    16. {
    17. for(int i=0;i<5;i++) scanf("%s",str[i]);
    18. int ans=7;
    19. for(int i=0;i<32;i++)
    20. {
    21. int cnt=0;
    22. memcpy(temp,str,sizeof str);
    23. for(int j=0;j<5;j++)//枚举改第一行的状态
    24. if(i>>j&1) cnt++,trans(0,j);
    25. for(int j=0;j<4;j++)//枚举改剩下的几行
    26. for(int k=0;k<5;k++)
    27. if(temp[j][k]=='0') cnt++,trans(j+1,k);
    28. for(int j=0;j<5;j++)//看看最后几行是不是全为1
    29. if(temp[4][j]=='0') cnt=0x3f3f3f3f;
    30. ans=min(cnt,ans);
    31. }
    32. if(ans<=6) printf("%d\n",ans);//假如小于6了
    33. else puts("-1");
    34. }
    35. int main()
    36. {
    37. int T;
    38. scanf("%d",&T);
    39. while(T--) solve();
    40. return 0;
    41. }

    7.带分数

    朴素思路:

    1.首先用全排列枚举1到9的所有方案

    2.枚举a b c的位数 (n=a+b/c)

    3.判断合不合法

    1. #include
    2. #include
    3. using namespace std;
    4. const int N = 10;
    5. int cnt=0;
    6. int num[9]={1,2,3,4,5,6,7,8,9};
    7. int cal(int i,int j)
    8. {
    9. int res=0;
    10. for(int k = i+1 ; k<=j ; k++)
    11. {
    12. res=res*10+num[k];
    13. }
    14. return res;
    15. }
    16. // 设target = a+b/c,
    17. int main()
    18. {
    19. int target;
    20. cin>>target;
    21. // 枚举1~9的所有情况
    22. do
    23. {
    24. for(int i = 0 ; i<9 ; i++) // 二重循环枚举组合
    25. {
    26. for(int j = i+1 ; j<9 ; j++)
    27. {
    28. int a = cal(-1,i);
    29. int b = cal(i,j);
    30. int c = cal(j,8);
    31. if(target*c==a*c+b)cnt++; // 注意,由于c++是整除运算,因此我们用乘法来替代除法
    32. }
    33. }
    34. }while(next_permutation(num,num+9));
    35. cout<
    36. return 0;
    37. }

    优化做法:

    首先n的在上面的做法是没用过的 因为是在枚举a b c 那么是不是就可以枚举 a b (n=a+b/c)  =>      ( b=n*c - a*c ) 然后通过这个式子就可以直接算出 b 了 就不用枚举了 那么我们在dfs a 选什么的时候 再 dfs c 选什么 再判断一下b合不合法就行了

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. const int N = 10;
    7. int n;
    8. bool st[N], backup[N];
    9. int ans;
    10. bool check(int a, int c)
    11. {
    12. long long b = n * (long long)c - a * c;//这个可能会溢出
    13. if (!a || !b || !c) return false;
    14. memcpy(backup, st, sizeof st);
    15. while (b)
    16. {
    17. int x = b % 10; // 取个位
    18. b /= 10; // 个位删掉
    19. if (!x || backup[x]) return false;
    20. backup[x] = true;
    21. }
    22. for (int i = 1; i <= 9; i ++ )
    23. if (!backup[i])
    24. return false;
    25. return true;
    26. }
    27. void dfs_c(int u, int a, int c)
    28. {
    29. if (u > 9) return;
    30. if (check(a, c)) ans ++ ;
    31. for (int i = 1; i <= 9; i ++ )
    32. if (!st[i])
    33. {
    34. st[i] = true;
    35. dfs_c(u + 1, a, c * 10 + i);
    36. st[i] = false;
    37. }
    38. }
    39. void dfs_a(int u, int a)
    40. {
    41. if (a >= n) return; //剪枝 a如果>=n 一定不是合法的
    42. if (a) dfs_c(u, a, 0);//如果a不为0是才去枚举c 一种剪枝
    43. for (int i = 1; i <= 9; i ++ )
    44. if (!st[i])
    45. {
    46. st[i] = true;
    47. dfs_a(u + 1, a * 10 + i);
    48. st[i] = false;
    49. }
    50. }
    51. int main()
    52. {
    53. cin >> n;
    54. dfs_a(0, 0);//选了0个数 a的取值为0
    55. cout << ans << endl;
    56. return 0;
    57. }

    8.飞行员兄弟

    这题又和费解的开关是同一类题 但是这题没有费解的开关那种性质了 按第一行并不能确定所有状态 所以我们直接二进制暴力枚举4*4的棋盘怎么按 就行了

    1. #include
    2. using namespace std;
    3. char g[7][7];
    4. char backup[7][7];
    5. int get(int a,int b)
    6. {
    7. return 4*a+b;
    8. }
    9. void turn(int a,int b)
    10. {
    11. if(g[a][b]=='+') g[a][b]='-';
    12. else g[a][b]='+';
    13. }
    14. int main()
    15. {
    16. for(int i=0;i<4;i++)
    17. cin>>g[i];
    18. vectorint,int>>res;
    19. for(int i=0;i<1<<16;i++)
    20. {
    21. vectorint,int>> t;
    22. memcpy(backup,g,sizeof g);
    23. for(int j=0;j<4;j++)
    24. for(int k=0;k<4;k++)
    25. {
    26. if(i>>get(j,k)&1)
    27. {
    28. t.push_back({j,k});
    29. for(int l=0;l<4;l++)
    30. turn(j,l),turn(l,k);
    31. turn(j,k);
    32. }
    33. }
    34. int fl=false;
    35. for(int j=0;j<4;j++)
    36. for(int k=0;k<4;k++)
    37. if(g[j][k]=='+')
    38. fl=true;
    39. if(!fl&&(!res.size()||res.size()>t.size()))
    40. res=t;
    41. memcpy(g,backup,sizeof backup);
    42. }
    43. cout<size()<
    44. for(int i=0;isize();i++)
    45. {
    46. cout<1<<" "<1<
    47. }
    48. return 0;
    49. }

    9.数的范围

    二分模板题

    我的总结 二分左右边界的时候不要想着模板 我个人觉得是真的乱

    二分的时候

    首先要自己自己二分的是左边界还是右边界

    然后再去将没有等号的判断条件放到你不需要的区间那里

    比如下面这段代码 我需要的是右边界 所以是左区间 那么我就把+1 -1 扔到这里右区间

    1. while(l
    2. {
    3. int mid=l+r>>1;
    4. if(a[mid]>=x) r=mid;
    5. else l=mid+1;
    6. }

    另外一个同理

    1. while(l
    2. {
    3. int mid=l+r+1>>1;
    4. if(a[mid]>x) r=mid-1;
    5. else l=mid;
    6. }

    代码实现

    1. #include
    2. using namespace std;
    3. const int N=1e5+10;
    4. int a[N];
    5. int main()
    6. {
    7. int n,q;
    8. scanf("%d%d",&n,&q);
    9. for(int i=0;i
    10. scanf("%d",&a[i]);
    11. while(q--)
    12. {
    13. int x;
    14. scanf("%d",&x);
    15. int l=0,r=n-1;
    16. while(l
    17. {
    18. int mid=l+r>>1;
    19. if(a[mid]>=x) r=mid;
    20. else l=mid+1;
    21. }
    22. if(a[l]==x)
    23. {
    24. printf("%d ",l);
    25. l=0,r=n-1;
    26. while(l
    27. {
    28. int mid=l+r+1>>1;
    29. if(a[mid]>x) r=mid-1;
    30. else l=mid;
    31. }
    32. printf("%d\n",l);
    33. }
    34. else printf("-1 -1\n");
    35. }
    36. return 0;
    37. }

    10.数的三次根

    这题也是二分逼近答案就好了

    浮点二分还比较简单 不用考虑边界问题

    1. #include
    2. using namespace std;
    3. const double eps=1e-8;
    4. int main()
    5. {
    6. double n;
    7. scanf("%lf",&n);
    8. double l=-10000,r=10000;
    9. while(r-l>eps)
    10. {
    11. double mid=(l+r)/2;
    12. if(mid*mid*mid>=n) r=mid;
    13. else l=mid;
    14. }
    15. printf("%lf\n",l);
    16. return 0;
    17. }

  • 相关阅读:
    Frequently used Docker commands on Ubuntu
    PostgreSQL 跨库查询配置
    金仓数据库兼容Oracle exp/imp的导出导入工具手册(2. 概述)
    岭回归和LASSO回归
    RK3568-tftp更新设备树和内核&nfs挂载文件系统
    大数据-之LibrA数据库系统告警处理(ALM-12043 DNS解析时长超过阈值)
    前端例程20220815:拟物风格复选按钮
    Python基于php+MySQL的英语学习交流平台
    OSN 1800 II TP机盒华为全新一代光层机盒
    OpenCV项目开发实战---进行曝光融合(使用不同曝光设置拍摄的图像组合成一张图像)
  • 原文地址:https://blog.csdn.net/lee_14141/article/details/127976621