问题描述
如下图所示,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回溯一些就过了。
附代码:
1 /* 2 好像是很直接的dfs+回溯 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <iostream> 8 #include <queue> 9 #define inf 100000000 10 using namespace std; 11 12 int mp[20][20]; 13 int ans, sum; 14 int n, m; 15 16 int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; 17 int vis[20][20]; 18 19 bool check(int a, int b) { 20 if (a >= 0 && a < n && b >= 0 && b < m && !vis[a][b]) { 21 return true; 22 } 23 return false; 24 } 25 26 void dfs(int x, int y, int num, int tsum) { 27 if (tsum == sum/2) { 28 if (ans > num) { 29 ans = num; 30 return; 31 } 32 } 33 34 for (int i=0; i<4; ++i) { 35 int tx = x + dir[i][0]; 36 int ty = y + dir[i][1]; 37 if (check(tx, ty)) { 38 vis[tx][ty] = 1; 39 dfs(tx, ty, num+1, tsum+mp[tx][ty]); 40 vis[tx][ty] = 0; 41 } 42 } 43 } 44 45 int main() { 46 while(cin >> m >> n) { 47 ans = inf; 48 sum = 0; 49 memset(vis, 0, sizeof(vis)); 50 51 for (int i=0; i<n; ++i) { 52 for (int j=0; j<m; ++j) { 53 cin >> mp[i][j]; 54 sum += mp[i][j]; 55 } 56 } 57 58 vis[0][0] = 1; 59 dfs(0, 0, 1, mp[0][0]); 60 cout << ans << endl; 61 } 62 return 0; 63 }