这题就是上一节的那题的扩展版了
首先第一行的状态如果确定了 那么后面要进行的操作也是确定的 所以枚举一下第一行的状态就好了
但是不同的是 上一题的第一个状态是确定的 但是这题的第一个状态不是确定的 因为可以通过按很多不同的按钮使得第一个的状态改变 而上一题只能有一个操作使得第一个状态的改变 所以这个还需要加一个二进制枚举一下第一行的状态 然后操作后面的按钮使得第一行全部变为符合要求的状态 再判断一下合法解
- #include
- using namespace std;
- const int N=6;
- char str[N][N],temp[N][N];
- int dx[6]={-1,0,1,0,0},dy[6]={0,1,0,-1,0};//上 右 下 左 中
- void trans(int x,int y)//用来改变一个位置
- {
- for(int i=0;i<5;i++)//枚举五个方向
- {
- int tx=x+dx[i],ty=y+dy[i];
- if(tx<0||tx>4||ty<0||ty>4) continue;
- temp[tx][ty]^=1;
- }
- }
- void solve()
- {
- for(int i=0;i<5;i++) scanf("%s",str[i]);
- int ans=7;
- for(int i=0;i<32;i++)
- {
- int cnt=0;
- memcpy(temp,str,sizeof str);
- for(int j=0;j<5;j++)//枚举改第一行的状态
- if(i>>j&1) cnt++,trans(0,j);
- for(int j=0;j<4;j++)//枚举改剩下的几行
- for(int k=0;k<5;k++)
- if(temp[j][k]=='0') cnt++,trans(j+1,k);
- for(int j=0;j<5;j++)//看看最后几行是不是全为1
- if(temp[4][j]=='0') cnt=0x3f3f3f3f;
- ans=min(cnt,ans);
- }
- if(ans<=6) printf("%d\n",ans);//假如小于6了
- else puts("-1");
- }
- int main()
- {
- int T;
- scanf("%d",&T);
- while(T--) solve();
- return 0;
- }
朴素思路:
1.首先用全排列枚举1到9的所有方案
2.枚举a b c的位数 (n=a+b/c)
3.判断合不合法
- #include
- #include
-
- using namespace std;
-
- const int N = 10;
- int cnt=0;
- int num[9]={1,2,3,4,5,6,7,8,9};
-
- int cal(int i,int j)
- {
- int res=0;
- for(int k = i+1 ; k<=j ; k++)
- {
- res=res*10+num[k];
- }
- return res;
- }
-
-
- // 设target = a+b/c,
- int main()
- {
- int target;
- cin>>target;
- // 枚举1~9的所有情况
- do
- {
- for(int i = 0 ; i<9 ; i++) // 二重循环枚举组合
- {
- for(int j = i+1 ; j<9 ; j++)
- {
- int a = cal(-1,i);
- int b = cal(i,j);
- int c = cal(j,8);
- if(target*c==a*c+b)cnt++; // 注意,由于c++是整除运算,因此我们用乘法来替代除法
- }
- }
- }while(next_permutation(num,num+9));
- cout<
- return 0;
- }
优化做法:
首先n的在上面的做法是没用过的 因为是在枚举a b c 那么是不是就可以枚举 a b (n=a+b/c) => ( b=n*c - a*c ) 然后通过这个式子就可以直接算出 b 了 就不用枚举了 那么我们在dfs a 选什么的时候 再 dfs c 选什么 再判断一下b合不合法就行了
- #include
- #include
- #include
- #include
-
- using namespace std;
-
- const int N = 10;
-
- int n;
- bool st[N], backup[N];
- int ans;
-
- bool check(int a, int c)
- {
- long long b = n * (long long)c - a * c;//这个可能会溢出
-
- if (!a || !b || !c) return false;
-
- memcpy(backup, st, sizeof st);
- while (b)
- {
- int x = b % 10; // 取个位
- b /= 10; // 个位删掉
- if (!x || backup[x]) return false;
- backup[x] = true;
- }
-
- for (int i = 1; i <= 9; i ++ )
- if (!backup[i])
- return false;
-
- return true;
- }
-
- void dfs_c(int u, int a, int c)
- {
- if (u > 9) return;
-
- if (check(a, c)) ans ++ ;
-
- for (int i = 1; i <= 9; i ++ )
- if (!st[i])
- {
- st[i] = true;
- dfs_c(u + 1, a, c * 10 + i);
- st[i] = false;
- }
- }
-
- void dfs_a(int u, int a)
- {
- if (a >= n) return; //剪枝 a如果>=n 一定不是合法的
- if (a) dfs_c(u, a, 0);//如果a不为0是才去枚举c 一种剪枝
-
- for (int i = 1; i <= 9; i ++ )
- if (!st[i])
- {
- st[i] = true;
- dfs_a(u + 1, a * 10 + i);
- st[i] = false;
- }
- }
-
- int main()
- {
- cin >> n;
-
- dfs_a(0, 0);//选了0个数 a的取值为0
-
- cout << ans << endl;
-
- return 0;
- }
这题又和费解的开关是同一类题 但是这题没有费解的开关那种性质了 按第一行并不能确定所有状态 所以我们直接二进制暴力枚举4*4的棋盘怎么按 就行了
- #include
- using namespace std;
- char g[7][7];
- char backup[7][7];
- int get(int a,int b)
- {
- return 4*a+b;
- }
- void turn(int a,int b)
- {
- if(g[a][b]=='+') g[a][b]='-';
- else g[a][b]='+';
- }
- int main()
- {
- for(int i=0;i<4;i++)
- cin>>g[i];
- vector
int,int>>res; - for(int i=0;i<1<<16;i++)
- {
- vector
int,int>> t; - memcpy(backup,g,sizeof g);
- for(int j=0;j<4;j++)
- for(int k=0;k<4;k++)
- {
- if(i>>get(j,k)&1)
- {
- t.push_back({j,k});
- for(int l=0;l<4;l++)
- turn(j,l),turn(l,k);
- turn(j,k);
- }
- }
- int fl=false;
- for(int j=0;j<4;j++)
- for(int k=0;k<4;k++)
- if(g[j][k]=='+')
- fl=true;
- if(!fl&&(!res.size()||res.size()>t.size()))
- res=t;
- memcpy(g,backup,sizeof backup);
- }
- cout<
size()< - for(int i=0;i
size();i++) - {
- cout<
1<<" "<1< - }
- return 0;
- }
9.数的范围
二分模板题
我的总结 二分左右边界的时候不要想着模板 我个人觉得是真的乱
二分的时候
首先要自己自己二分的是左边界还是右边界
然后再去将没有等号的判断条件放到你不需要的区间那里
比如下面这段代码 我需要的是右边界 所以是左区间 那么我就把+1 -1 扔到这里右区间
- while(l
- {
- int mid=l+r>>1;
- if(a[mid]>=x) r=mid;
- else l=mid+1;
-
- }
另外一个同理
- while(l
- {
- int mid=l+r+1>>1;
- if(a[mid]>x) r=mid-1;
- else l=mid;
- }
代码实现
- #include
- using namespace std;
- const int N=1e5+10;
- int a[N];
- int main()
- {
- int n,q;
- scanf("%d%d",&n,&q);
- for(int i=0;i
- scanf("%d",&a[i]);
- while(q--)
- {
- int x;
- scanf("%d",&x);
- int l=0,r=n-1;
- while(l
- {
- int mid=l+r>>1;
- if(a[mid]>=x) r=mid;
- else l=mid+1;
-
- }
- if(a[l]==x)
- {
- printf("%d ",l);
- l=0,r=n-1;
- while(l
- {
- int mid=l+r+1>>1;
- if(a[mid]>x) r=mid-1;
- else l=mid;
- }
- printf("%d\n",l);
- }
- else printf("-1 -1\n");
- }
- return 0;
- }
10.数的三次根
这题也是二分逼近答案就好了
浮点二分还比较简单 不用考虑边界问题
- #include
- using namespace std;
- const double eps=1e-8;
- int main()
- {
- double n;
- scanf("%lf",&n);
- double l=-10000,r=10000;
- while(r-l>eps)
- {
- double mid=(l+r)/2;
- if(mid*mid*mid>=n) r=mid;
- else l=mid;
- }
- printf("%lf\n",l);
- return 0;
- }
-
相关阅读:
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