目录
题目链接:116. 飞行员兄弟 - AcWing题库
题目思路:
代码详解:
题目链接:116. 飞行员兄弟 - AcWing题库
题目思路:
1.我们可以知道
对于任意一个点
重复的按两次的话
回不改变原状态
而题目所求为最少次数
故每个每个点最多按一次
2.因为所给的矩阵为4*4的矩阵
且由思路1我们可以得到
对于每个位置只有两种情况
按或者不按
我们可以用二进制中的
1表示按这个位置,0表示不按这个位置
而这样操作的时间复杂度为
2^16=65536
每次只需要对2进制中的0和1
对于于对数组进行的操作
大约时间复杂度可估计为
2^16(遍历二进制的数)*16(遍历二进制的位数上的0和1)*4(对数组行和列进行翻转)
=4194304(小于1千万次【10^7】)
故可得该方法可行
代码详解:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=5;
#define x first
#define y second
typedef pair<int,int> PII;
vector<PII> ans;
char arr[N][N];
char backup[N][N];
int change(int x,int y){//把数组i和j代表的位置转换为图中二进制所代表的位置
return x*4+y;
}
void turn(int x,int y){//进行翻转操作
for(int i=0;i<4;i++){
if('+'==backup[x][i]) backup[x][i]='-';
else backup[x][i]='+';
if('+'==backup[i][y]) backup[i][y]='-';
else backup[i][y]='+';
}
if('+'==backup[x][y]) backup[x][y]='-';
else backup[x][y]='+';
}
int main(){
for(int i=0;i<4;i++){
scanf("%s",&arr[i]);
}
for(int i=0;i<1<<16;i++)
{
memcpy(backup,arr,sizeof arr);//拷贝数组
vector<PII> temp;
for(int m=0;m<4;m++){
for(int n=0;n<4;n++){//遍历数组
int t=change(m,n);//对所在位置转换为二进制所在第几位
if(i>>t&1){//如果该位置为1
turn(m,n);
temp.push_back({m,n});
}
}
}
int flag=1;
for(int m=0;m<4;m++)
for(int n=0;n<4;n++)
if('+'==backup[m][n]) flag=0;//如果仍然存在+,那么该方法不行
if(1==flag){//检查是否可行
if(ans.empty()||ans.size()>temp.size()){//检查是否比之前所用次数少
ans=temp;
}
}
}
printf("%d\n",ans.size());
for(auto pos:ans){
cout<<pos.x+1<<" "<<pos.y+1<<endl;
}
return 0;
}
PS:我与将心向明月,奈何明月照沟渠。