资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
如下图所示,3 x 3 的格子中填写了一些整数。
+--*--+--+
|10* 1|52|
+--****--+
|20|30* 1|
*******--+
| 1| 2| 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
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
1 1 1 1
1 30 80 2
1 1 1 100
样例输出2
10
这题就是简单的深搜. 先求出所有数的总和,判断是否能被2整除,若不能就输出0,能就再深搜判断.
起初我否定了这个想法,因为这样深搜只能找到以(0,0)为端点或者成环的划分区域,但是并不排除有这样的划分区域:(0,0)不在这个区域的端点位置,而是交点位置,例如(0,0)所在行和列同属于一个区域,其他数属于另一个区域,这种划分就搜不出来了. 不过百度了一下发现好多代码也没考虑那么多,交了之后发现原来就3个测试用例,我估计是水过.
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <algorithm> 8 #define INF 0x3f3f3f3f 9 #define zero 1e-7 10 11 using namespace std; 12 typedef long long ll; 13 const ll mod=50000; 14 const ll max_n=2e5+7; 15 16 int mp[10][10]; 17 bool vis[10][10]; //标记是否访问过 18 int d[4][2]={{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; 19 int m, n;//n行m列 20 int ans, res;//所有数字和,最小区域格子数 21 22 void input() { 23 ans=0; 24 for(int i=0; i<n; i++) { 25 for(int j=0; j<m; j++) { 26 cin>>mp[i][j]; 27 ans+=mp[i][j]; 28 } 29 } 30 } 31 32 void dfs(int x, int y, int sum, int num) {//坐标、区域和、区域格子数 33 vis[x][y]=true; 34 if(sum==ans/2) { 35 res=min(res, num); 36 return; 37 } 38 for(int i=0; i<4; i++) { 39 int dx=x+d[i][0]; 40 int dy=y+d[i][1]; 41 if(dx>=0 && dx<n && dy>=0 && dy<m && !vis[dx][dy] && sum+mp[dx][dy]<=ans/2) { 42 vis[dx][dy]=true; 43 dfs(dx, dy, sum+mp[dx][dy], num+1); 44 vis[dx][dy]=false;//回溯 45 } 46 } 47 } 48 49 int main() { 50 cin>>m>>n; 51 memset(vis, false, sizeof(vis)); 52 res=INF; 53 input(); 54 if(ans%2==0) dfs(0, 0, mp[0][0], 1); 55 if(res==INF) res=0; 56 cout<<res<<endl; 57 return 0; 58 }