历届试题 剪格子

问题描述

如下图所示,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
 
意思是将N行M列的数字剪成两个区域,问是否存在一种剪法使得两个区域的和相等,如果有多种剪法,取左上角格子所在的区域能包含的最小格子数。
DFS寻找上下左右四个方向位置取值即可;
1.只有偶数才会存在两个区域相等;
2.判断一下边界以及其中一个区域<=sum/2。
 
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,sum=0,ans;
 4 int a[15][15],dir[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
 5 bool vis[15][15];
 6 int fun()
 7 {
 8     int cnt=0;
 9     for(int i=0;i<n;i++){
10         for(int j=0;j<m;j++){
11             if(vis[i][j])    //从左上角开始的DFS,左上角的格子一定是访问过的,所以寻找访问过的格子就行
12                 cnt++;
13         }
14     }
15     return cnt;
16 }
17 void dfs(int x,int y,int temp)
18 {
19     if(temp == sum/2)
20         ans = fun();
21     else{
22         for(int i=0;i<4;i++){
23             int fx=x+dir[i][0];
24             int fy=y+dir[i][1];
25             if(fx>=0&&fy>=0&&fx<n&&fy<m&&!vis[fx][fy]&&temp+a[fx][fy]<=sum/2){
26                 vis[fx][fy]=1;
27                 dfs(fx,fy,temp+a[fx][fy]);
28                 vis[fx][fy]=0;
29             }
30         }
31     }
32 }
33 int main()
34 {
35     memset(a,0,sizeof a);
36     memset(vis,0,sizeof vis);
37     cin>>m>>n;
38     for(int i=0;i<n;i++){
39         for(int j=0;j<m;j++){
40             cin>>a[i][j];
41             sum+=a[i][j];
42         }
43     }
44     if(sum%2==0){
45         if(a[0][0]==sum/2) ans=1;
46         else{
47             vis[0][0]=1;
48             dfs(0,0,a[0][0]);
49         }
50     }
51     else ans=0;
52     cout<<ans<<endl;
53     return 0;
54 }
View Code

 

 
posted @ 2020-03-04 17:58  PeacefulGemini  阅读(387)  评论(0)    收藏  举报
回顶部