开始做一点简单的oj,在网上看到了一套题单,是按算法类型和难度等级列出的。对我等入门新手十分友善,所以按照顺序往下刷并自学一些算法。开这个博客也主要是为了放一些学习笔记,保存刷题进度。
枚举法是入门第一种算法,poj的1753和2965都是属于顺序没什么关系的枚举。
以下贴代码
2965
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int Rounds=0;
char board[4][4];
vector<int> v;
vector<int> m;
vector<int> minM;
void readBoard(){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
cin>>board[i][j];
}
}
}
bool ok(){
char c='-';
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(board[i][j]!=c)
return false;
}
}
return true;
}
void flip(int i,int j){
if(board[i][j]=='-')
board[i][j]='+';
else
board[i][j]='-';
}
void change(int i,int j){
if((i>=0&&i<4)&&(j>=0&&j<4)){
for(int m=0;m<4;m++){
flip(i,m);
flip(m,j);
}
flip(i,j);
}
}
void print(){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
cout<<board[i][j];
}
cout<<endl;
}
}
void searchfor_flip(int i, int j){
if(ok()){
if(v.empty()||Rounds<*min_element(v.begin(), v.end())){
v.push_back(Rounds);
minM=m;
}
return;
}
if(i>=4) return;
change(i,j);Rounds++;
m.push_back(i);
m.push_back(j);
if(j<3){searchfor_flip(i, j+1);}
else searchfor_flip(i+1, 0);
Rounds--;
change(i, j);
m.pop_back();
m.pop_back();
if(j<3) searchfor_flip(i,j+1);
else searchfor_flip(i+1, 0);
}
void show(){
if(v.empty())
cout<<"Impossible";
else{
int Min=*min_element(v.begin(), v.end());
cout<<Min<<endl;
for(int i=0;i<Min*2;i=i+2){
cout<<minM[i]+1<<' '<<minM[i+1]+1<<endl;
}
}
}
int main(int argc, const char * argv[]) {
// insert code here...
readBoard();
searchfor_flip(0, 0);
show();
return 0;
}
1753和2965的方法格式基本是一样的,不过后者多了一个要存储最短路径的走法而不是直接输出结果。
写完1753之后参考了一篇discuss中ac代码,学习到了要充分使用<algorithm>中的排序和vector十分友善的存储方法。
还有无关顺序的枚举法使用的,按顺序走然后逐次跳回的方法。
再写2965的时候就快了很多,一次ac(哈哈哈哈),虽然还是因为从别人的代码里学到了很多。
总结一个就是有关翻转,而且只有两种结果非黑即白的情况下,基本都是无关顺序的。