第四届蓝桥杯省赛C++A组 剪格子

第四届蓝桥杯省赛C++A组 剪格子

题目链接:

http://lx.lanqiao.cn/problem.page?gpid=T27

思路:

直接dfs搜索一波,以左上角为起点。
说明: 有些特殊情况无法解决:
1.不经过左上角
例如:这种情况存在一个环,也会导致解法加一(顺时针的环和逆时针的环)
第四届蓝桥杯省赛C++A组 剪格子_第1张图片
2.dfs搜索路径类似一笔画,类似T字形无法搜索
第四届蓝桥杯省赛C++A组 剪格子_第2张图片
3.不过蓝桥杯的测试系统,也没考虑以上两种情况

代码:

#include 
#include 
#include 
#include 
#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;
}

你可能感兴趣的:(蓝桥杯,dfs,算法)