分析
递归版运行速度提升很大,个人认为主要原因是递归的过程中记录了中间态(利用全局变量st),而循环写法每次将st重置,没有利用中间过程。
递归
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 4;
char st[N+1][N+1];
vector<pair<int, int > > res;
vector<pair<int, int > > path;
//char back[N+1][N+1];
//char back
void turn(int row, int col){
for(int i = 0; i < 4; i++){
st[row][i] = st[row][i] == '+' ? '-' : '+';
st[i][col] = st[i][col] == '+' ? '-' : '+';
}
// (row, col) 已经改变了2次,等于没变
st[row][col] = st[row][col] == '+' ? '-' : '+';
}
bool judge(){
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
if(st[i][j] == '+')
return false;
return true;
}
int cnt = 0;
void dfs(int pos) {
if(pos == 16) {
// 2. 判断是否更新res
if(judge())
if(res.empty()|| res.size() < path.size()) {
res = path;
}
// 1. return
return;
}
// 1. 备份状态
char back[N+1][N+1];
memcpy(back, st, sizeof(st));
// 2. 改变状态
turn(pos/4, pos%4);
path.push_back({pos/4, pos%4});
// 3. 分支:对x,y位置操作
dfs(pos+1);
// 4. 恢复现场
/*
*
* 恢复现场:注意全局变量和局部变量,
* back必须是局部变量,用来恢复现场
* path是全局需要pop, 用来记录最终结果,
*
*/
memcpy(st, back, sizeof(st));
path.pop_back();
// 5. 分支:对x,y位置不操作
dfs(pos+1);
}
int main(int argc, char** argv) {
for(int i = 0; i < 4; i++)
cin >> st[i];
dfs(0);
cout << res.size() << endl;
for(auto &p: res)
cout << p.first +1 << " " << p.second+1 << endl;
return 0;
}
循环
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 4;
char st[N+1][N+1];
char back[N+1][N+1];
void turn(int row, int col){
for(int i = 0; i < 4; i++){
st[row][i] = st[row][i] == '+' ? '-' : '+';
st[i][col] = st[i][col] == '+' ? '-' : '+';
}
// (row, col) 已经改变了2次,等于没变
st[row][col] = st[row][col] == '+' ? '-' : '+';
}
bool judge(){
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
if(st[i][j] == '+')
return false;
return true;
}
int main(int argc, char** argv) {
for(int i = 0; i < 4; i++)
cin >> st[i];
memcpy(back, st, sizeof(st)); // 全局变量back用于恢复状态
vector<pair<int, int > > res;
for(int op = 0; op < 1 << 16; op++){
vector<pair<int, int > > path; // 初始化,如果是全局path,需要clear()
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
// if(st[i][j] == '+'){// 有问题!!!!
// turn(i,j);
// path.push_back({i,j});
// }
if(op >> i*4+j & 1){// 重点!
turn(i,j);
path.push_back({i,j});
}
if(judge())
if(res.empty() || res.size() > path.size())
res = path;
//
memcpy(st, back, sizeof(back));
}
cout << res.size() << endl;
for(auto &p: res)
cout << p.first +1 << " " << p.second+1 << endl;
return 0;
}