问题描述
如下图所示,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
记:
一开始写了个dfs+回溯的,但由于回溯写法有问题,一直没成功
恍然大悟
(ps:dfs的题型仍需要加强训练)
示例代码:
1 #include <stdio.h> 2 #define LEN 10 3 #define MIN(X,Y) (X)<(Y)?(X):(Y) 4 5 int n,m; /*表格的宽度和高度*/ 6 int sum = 0; 7 int count = 99999999; /*含左上角区域的最小格数*/ 8 int arr[LEN+1][LEN+1] = {0}; /*存储数据*/ 9 int vis[LEN+1][LEN+1] = {1,0}; /*访问标记*/ 10 int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1},};/*[x][0]->x(行),[x][1]->y(列)*/ 11 12 13 void dfs(int x,int y,int s,int step) 14 { 15 int i; 16 int nx,ny; 17 if (s >= sum) 18 { 19 if (s == sum) 20 { 21 count = MIN(step,count); 22 } 23 return ; 24 } 25 26 for (i = 0 ; i < 4 ; i ++) 27 { 28 nx = x + dir[i][0]; 29 ny = y + dir[i][1]; 30 if (0<nx && 0<ny && nx<=n && ny<=m && !vis[nx][ny]) 31 { 32 vis[nx][ny] = 1; 33 dfs(nx,ny,s+arr[nx][ny],step+1); 34 vis[nx][ny] = 0; 35 } 36 } 37 return ; 38 } 39 40 int main(void) 41 { 42 int i,j; 43 scanf("%d %d",&m,&n); 44 for (i = 1 ; i <= n ; i ++) 45 { 46 for (j = 1 ; j <= m ; j ++) 47 { 48 scanf("%d",&arr[i][j]); 49 sum += arr[i][j]; 50 } 51 } 52 53 if (sum%2 == 0) 54 { 55 sum /= 2; 56 dfs(1,1,arr[1][1],1); 57 printf("%d",count); 58 } 59 else 60 { 61 printf("%d",0); 62 } 63 return 0; 64 }