剪格子 dfs 蓝桥杯

时间:2023-03-09 00:21:27
剪格子    dfs  蓝桥杯

问题描述 
如下图所示,3  x  3  的格子中填写了一些整数。 
+--*--+--+ 
|10*  1|52| 
+--****--+ 
|20|30*  1| 
*******--+ 
|  1|  2|  3| 
+--+--+--+ 
我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60。 
本题的要求就是请你编程判定:对给定的m  x  n  的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。 
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。 
如果无法分割,则输出  0。

输入格式 
程序先读入两个整数  m  n  用空格分割  (m,n< 10)。 
表示表格的宽度和高度。 
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000。 
输出格式 
输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。

样例输入1 
3  3 
10  1  52 
20  30  1 
1  2  3 
样例输出1 
3

样例输入2 
4  3 
1  1  1  1 
1  30  80  2 
1  1  1  100 
样例输出2 
10

#include<stdio.h>
#include<string.h>
#include<algorithm>
int n,m,a[][],b[][],su;
int so[][]={,,-,,,,,-}; //搜索方向
using namespace std;
int dfs(int x,int y,int sum)
{
int x1,y1,i,ans=;
if(sum==su)    //满足要求,搜索结束,此次搜索有效
return ;
for(i=;i<;i++)  //四个方向
{
x1=x+so[i][];  // x1,y1为按方向移动后的坐标
y1=y+so[i][];
if(x1<n && x1>= && y1<m && y1>=)  //判断是否出界
{
if(b[x1][y1]== && a[x1][y1]+sum<=su)  //判断是否已搜索过&&本次搜索是否可执行
{
b[x1][y1]=;      //标记,代表已搜索该点
ans=dfs(x1,y1,a[x1][y1]+sum);    //ans代表下一个搜索点到此点的步数
if(ans)          //如果ans不为零说明后续可走,为0则说明此步不可用,取消标记
return ans+;     
b[x1][y1]=;
}
}
}
return ;
}
int main()
{
int i,j,sum=;
scanf("%d%d",&m,&n);
memset(b,,sizeof(b));
for(i=;i<n;i++)
for(j=;j<m;j++)
{
scanf("%d",&a[i][j]);
sum+=a[i][j];
}
if(sum%==)
printf("0\n");
else
{
su=sum/;
b[][]=;
printf("%d\n",dfs(,,a[][]));
}
return ;
}