当前位置: 代码迷 >> 综合 >> 蓝桥杯 - 历届试题 剪格子
  详细解决方案

蓝桥杯 - 历届试题 剪格子

热度:87   发布时间:2023-10-09 15:53:15.0

问题描述

如下图所示,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


题目思路:

题目中要求将m*n的方格分成两部分,并且两部分的和是相同的,那么也就是我们只要保证其中一部分的和是总和的一半即可。另外题目中还提到要包含左上角的那个点即(0,0)点。因为格子一定是连续的,所以我们可以从(0,0)点开始搜索(四个方向)搜索边界是当前和大于等于总和的一半。当和超过一半的时候,一定要记得回溯。

题目代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;int n, m; 
int a[11][11], all = 0, ans = 11*11;
int dir[4][2] = {0,1, 0,-1, -1,0, 1,0};
int vis[11][11];
// x y 表示当前搜索起点的坐标
// sum 表示到当前搜索位置的和
// cnt表示到当前搜索位置的格子个数 
void dfs(int x, int y, int sum, int cnt)
{if(sum > all/2) return;if(sum == all/2){//寻找最小值 ans = min(ans,cnt);	}for(int i = 0; i < 4; i++){int xx = x + dir[i][0];int yy = y + dir[i][1];if(xx >= 0 && xx < m && yy >= 0 && yy < n && !vis[xx][yy]){vis[xx][yy] = 1;dfs(xx,yy, sum+a[xx][yy], cnt+1);vis[xx][yy] = 0;}}
}int main()
{scanf("%d%d", &n, &m);for(int i = 0; i < m; i++)for(int j = 0; j < n; j++){scanf("%d",&a[i][j]);all += a[i][j]; //求所有格子的总和 }//初始化 memset(vis,0,sizeof(vis));vis[0][0] = 1;dfs(0,0,a[0][0],1);	if(ans == 11*11){printf("-1");}else{printf("%d\n",ans);}}



  相关解决方案