历届试题 剪格子  
时间限制: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。

输出格式
输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。
样例输入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
 
算法思想:从格子的(0,0)(a[0][0])向四周开始搜索相加,当搜索得到的值(ans)等于总值(sum)的一半时满足。然后我们找出最小的cut就OK了,b[12][12]也要记得回溯。具体看代码:
 
 1 #include<stdio.h>
 2 #include<string.h>
 3 int dx[4]={0,0,1,-1};    //x的4个方向
 4 int dy[4]={1,-1,0,0};    //y的4个方向
 5 int sum = 0,cut1 = 101;    //最小格子数目不可能大于101
 6 int n,m;
 7 int a[12][12],b[12][12];
 8 void dfs(int x,int y,int ans,int cut)
 9 {
10     int i;
11     if(ans == sum/2)
12         cut1 = cut1>cut?cut:cut1;    //找最小的格子数目
13     for(i=0; i<4; i++)
14     {
15         int x1 = x+dx[i];
16         int y1 = y+dy[i];
17         if(x1<0 || x1>=4 || y1<0 || y1>=4 || b[x1][y1] || (ans > sum/2))    //约束条件
18             continue;
19         b[x1][y1] = 1;
20         dfs(x1,y1,ans+a[x1][y1],cut+1);
21         b[x1][y1] = 0;
22 
23     }
24 }
25 int main()
26 {
27     int i,j;
28     scanf("%d%d",&m,&n);
29     for(i=0; i<n; i++)
30     {
31         for(j=0; j<m; j++)
32         {
33             scanf("%d",&a[i][j]);
34             sum+=a[i][j];
35         }
36     }
37     if(sum%2)    //总和不能为奇数
38         printf("0\n");
39     else
40     {
41         memset(b,0,sizeof(b));
42         b[0][0] = 1;
43         dfs(0,0,a[0][0],1);
44         printf("%d\n",cut1);
45     }
46     return 0;
47 }

 

版权声明:本文为-skyblue原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/-skyblue/p/9438775.html