题目:
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。 (仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
正确答案在下面!!
(错误答案大神们请无视….)
Wrong Answer:
错因:这道题是不能边用dfs边判断,
比如图3的情况就不能考虑到:第2行第1列的格子可以选,
但是我写的代码里面就不能选,因为它的上面和左面的格子都没有被选过
而且!!我一开始的判断代码是错的,因为我判断了它左上角和右上角的格子,大概是判断代码写习惯了
搞了好几天才终于知道错误原因,( ! ^ ! )
//剪邮票
//wrong answer
#include<bits/stdc++.h>
using namespace std;
int cnt = 0;
bool selected[5][5];
int row,col,num;//num:要剪下来的个数
bool alright(int x, int y,int cur){
if(cur == 0) return true;
int xx = x - 1,yy = y - 1;
//上面
if(xx >= 1){
if(selected[xx][y]) return true;
}
//左面
if(yy >= 1){
if(selected[x][yy]) return true;
}
return false;
/*wrong answer
for(int dx = -1; dx <= 1; ++dx){
for(int dy = -1; dy <= 1; ++dy){
int xx = x + dx, yy = y + dy;
if(xx < 1 || yy < 1 || xx > row || yy > col) continue;
if(dx != 0 || dy != 0){
if(selected[xx][yy]) return true;
}
}
}
return false;
*/
}
void dfs(int x, int y,int cur){
if(cur == num){
cnt++;
return ;
}
if(cur < num && x > row) return ;
//选
if(alright(x, y,cur)){
selected[x][y] = true;
if( y == col) dfs(x + 1,1,cur + 1);
else dfs(x, y + 1, cur + 1);
selected[x][y] = false;
}
//不选
selected[x][y] = false;
if(y == col) dfs(x + 1, 1, cur);
else dfs(x, y + 1, cur);
}
int main(){
row = 3;
col = 4;
num = 5;
for(int i = 1; i <= row; ++i){
for(int j = 1; j <= col; ++j){
selected[i][j] = false;
}
}
dfs(1,1,0);
cout<<cnt<<endl;
return 0;
}
思路:
用DFS;递归深度为格子数(3 * 4 = 12),每个格子有两种可能的选择:选or不选,递归出口为已选择的格子数为5;应该是选完5个格子后再判断是否满足上下左右相邻的条件,不能边选边判断;判断1个连通块包含的格子数用普通递归orDFS(这里我用的普通的递归)
PS:调试是个好东西!输出结果出错时在DFS里面多用下输出调试看看哪步出错
答案:116
Code:
//剪邮票 答案:116
#include<bits/stdc++.h>
using namespace std;
int cnt = 0;
int selected[5][5];
int row,col,num;//num:要剪下来的个数
bool vis[5][5];
int unitcnt = 0;
int move[4][2] = {{-1, 0}, {0, -1},{0, 1}, {1, 0}};
int getsum(int x, int y){
if(x < 1 || y < 1 || x > row || y > col) return 0;
if(selected[x][y] == 0) return 0;
if(vis[x][y]) return 0;
vis[x][y] = true;
return 1 + getsum(x - 1, y) + getsum(x, y - 1) + getsum(x + 1,y) + getsum(x, y + 1);
}
void dfs(int x, int y,int cur){
if(cur == num){
// cout<<"cur == num"<<endl;
int i,j;
bool flag = false;
for(i = 1; i <= row; ++i){
for(j = 1; j <= col; ++j){
// cout<<"selected[] = "<<selected[i][j]<<endl;
if(selected[i][j] == 1){
flag = true;
break;
}
}
if(flag) break;
}
for(int k = 1; k <= row; ++k){
for(int t = 1; t <= col; ++t){
vis[k][t] = false;
}
}
// cout<<"selected[] = "<<selected[i][j]<<endl;
if(getsum(i,j) == num) cnt++;
return ;
}
if(cur < num && x > row) return ;
//选
selected[x][y] = 1;
if( y == col) dfs(x + 1,1,cur + 1);
else dfs(x, y + 1, cur + 1);
selected[x][y] = 0;
//不选
selected[x][y] = 0;
if(y == col) dfs(x + 1, 1, cur);
else dfs(x, y + 1, cur);
}
int main(){
row = 3;
col = 4;
num = 5;
for(int i = 1; i <= row; ++i){
for(int j = 1; j <= col; ++j){
selected[i][j] = 0;
}
}
dfs(1,1,0);
cout<<cnt<<endl;
return 0;
}