蓝桥杯 历届试题 剪格子(dfs)

    xiaoxiao2021-03-25  90

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

    这题数据给的很水,只有三组数据,也许题目给的不严谨,如果说能连成一条线,dfs肯定可解(需把每个点作为起点)。然而如无法连成一条线,那dfs貌似不能解。这题争议挺大的。看两组数据

    3 3 1 2 1 3 1 2 1 1 0

    答案是:3 (dfs可解)

    100  100  100 100 100  1       1      100 100  100  1       1 100  1       1       894

    这组数据就有问题了……

    那下面是在蓝桥上的AC代码:

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=10+2; int g[maxn][maxn]; int m,n; int sum; int min_num; int dir[][2]={{-1,0},{1,0},{0,-1},{0,1}}; int vis[maxn][maxn]; void dfs(int i,int j,int tol,int cnt){ if(i<0 || i>=n || j<0 || j>=m || vis[i][j] ||vis[i][j]>sum/2) return ; if(tol==sum/2 && vis[0][0]){ //是一半,并且第一个包含在内 min_num=min(min_num,cnt); return ; } for(int k=0;k<4;k++){ int x=dir[k][0]+i,y=dir[k][1]+j; vis[i][j]=1; dfs(x,y,tol+g[x][y],cnt+1); vis[i][j]=0; } } int main(){ while(scanf("%d%d",&m,&n)==2){ sum=0; for(int i=0;i<n;i++) for(int j=0;j<m;j++){ scanf("%d",&g[i][j]); sum+=g[i][j]; } memset(vis,0,sizeof(vis)); min_num=200; if(sum%2==0){ for(int i=0;i<n;i++) for(int j=0;j<m;j++) dfs(i,j,g[i][j],1); if(min_num!=200)printf("%d\n",min_num); else printf("0\n"); } else printf("0\n"); } return 0; } 如有不对的地方,谢谢指出!

    转载请注明原文地址: https://ju.6miu.com/read-26241.html

    最新回复(0)