第四届蓝桥杯省赛C++A组 剪格子
题目链接:
http://lx.lanqiao.cn/problem.page?gpid=T27
思路:
直接dfs搜索一波,以左上角为起点。
说明: 有些特殊情况无法解决:
1.不经过左上角
例如:这种情况存在一个环,也会导致解法加一(顺时针的环和逆时针的环)
2.dfs搜索路径类似一笔画,类似T字形无法搜索
3.不过蓝桥杯的测试系统,也没考虑以上两种情况
代码:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define ll long long
using namespace std;
int half,st=1000,count=0;
//half为总和的一半,st为走的步数,count表示count种可行的解法
int n,m;
int a[10][10];//待输入数组
int vis[10][10];//标记数组
int plus1[4][2]= {1,0 ,0,1, -1,0, 0,-1};//四种走法,下,右,上,左
void dfs(int x,int y,int step) {//x,y是坐标,step是步数
if(x<0||x>=n||y<0||y>=m)//超过边界,return
return;
if(x>=0&&x<m&&y>=0&&y<n) {
int sum=0;
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++)
if(vis[i][j]==1)
sum+=a[i][j];//计算已走过的数的总和
}
if(sum==half) {//满足条件
count++;//解法加一
if(step+1<st)//比较不同解法的步数
st=step+1;
//st=step+1(例如当左上角第一个格子的数就等于half,step=0,显然这是step需要加一)
return;
}
}
for(int i=0; i<4; i++) {//遍历四种走法,即四个子节点(实际是一个父节点和三个子节点)
int x1=x+plus1[i][0];
int y1=y+plus1[i][1];
if(!vis[x1][y1]) {//避免访问父节点
vis[x1][y1]=1;//标记
dfs(x1,y1,step+1);
vis[x1][y1]=0;//回溯
}
}
}
int main() {
cin>>m>>n;
int sum=0;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++) {
cin>>a[i][j];
sum+=a[i][j];
}
half=sum/2;//计算half
vis[0][0]=1;//默认第一个格子为起点
//也可以不置vis[0][0]=1,这样st=step,不用加一了
dfs(0,0,0);
if(count==0)//无法分割输出0
cout<<0<<endl;
else//可以分割输出包含左上角最少的
cout<<st<<endl;
return 0;
}