题目描述
历届试题 剪格子
时间限制:1.0s 内存限制:256.0MB
问题描述
如下图所示,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。
输出格式
输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。
样例输入
3 3 10 1 52 20 30 1 1 2 3
样例输出
3
参考代码
#include<iostream>
#include<climits>
using namespace std;
int n,m;
int map[15][15];//存储图数据
bool vis[15][15];//标记是否访问
int s=0;//表示图的和
bool flag=false;//标记是否有正确答案
int res=INT_MAX;//满足题目要求的最小格子数
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}}; //搜索方向
bool in(int x,int y){//判断是否越界 return 1<=x&&x<=m&&1<=y&&y<=n;
}
void dfs(int x,int y,int num,int sum){//num代表格子数目,sum代表数字的和 if(sum>s/2 || num>=res)//剪枝 return;if(sum==s/2) {//截止条件 flag=true; res=num;//通过剪枝操作,保证了res<num return;}for(int i=0;i<4;++i){//搜索条件 int tx=x+dir[i][0];int ty=y+dir[i][1];if(in(tx,ty)&&vis[tx][ty]==false){//坐标在图内,并且未被访问 vis[tx][ty]==true;dfs(tx,ty,num+1,sum+map[tx][ty]);//递归搜索vis[tx][ty]=false;//回溯,用于下一次搜索 } }
}
int main(){cin>>n>>m;for(int i=1;i<=m;++i){for(int j=1;j<=n;++j){cin>>map[i][j];vis[i][j]=false;s+=map[i][j];}} if(s%2!=0){cout<<0<<endl;return 0;}vis[1][1]=true;dfs(1,1,1,map[1][1]);if(flag==true)cout<<res<<endl;elsecout<<0<<endl;return 0;
}