趣味剪格子

如下图所示,3×3 的格子中填写了一些整数。

我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是 60。
本题的要求就是请你编程判定:对给定的 m×n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。 
如果无法分割,则输出 0。

输入输出格式
输入格式
第一行输入两个整数 m 和 n,表示表格的宽度和高度,每个整数用一个空格隔开。 
接下来输入 n 行,每行输入 m 个正整数,每个整数不大于 10000,每个正整数用一个空格隔开。 
输出格式
输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。 

输入输出样例1
输入

3 3
10 1 52
20 30 1
1 2 3 
输出


输入输出样例2
输入

2 2
10 15
5 2 
输出


说明提示
m,n<10

//使用c++深度优先搜索算法解决

#include <iostream>

#include <vector>

#include <climits>

using namespace std;

#define MAX_N 10

vector<vector<int>>grid;

vector<int> temp1;

int res=INT_MAX;

//使用#include<climits>

int ave;

//存储平均值

bool visit[MAX_N][MAX_N];

//记录当前格子又没有被访问

int m,n;

//移动数组

int x[]={-1,1,0,0};

int y[]={0,0,-1,1};

//深度优先搜索解决

void dfs(int index1,int index2,int currsum){

//index1 index2当前到达的位置

//currsum存储范围过的格子数字之和

    if(currsum>ave)return;

//剪枝操作

    if(currsum==ave){

        int temp=temp1.size();

        res=min(res,temp);

//记录最小格子数量

        return;

    }

    for(int i=0;i<4;i++){

        int a=index1+x[i],b=index2+y[i];

        if(!visit[a][b]){

            if(a<0||a>=m||b<0||b>=n)continue;        

            visit[a][b]=true;

            temp1.push_back(grid[a][b]);

            dfs(a,b,currsum+grid[a][b]);

                temp1.pop_back();

        //记录格子数量

//回溯,恢复现场

            visit[a][b]=false;

        }

    }

}

int main(){

    cin>>m>>n;

    int sum=0;

    //存储格子

    for(int i=0;i<m;i++){

        vector<int> temp;

        for(int j=0;j<n;j++){

            int num;

            cin>>num;

            sum+=num;

            temp.push_back(num);

        }

        grid.push_back(temp);

    }

    if(sum%2!=0)

//如果格子是奇数,就一定没有结果

    {cout<<0<<endl;

    return 0;}

    else{

        ave=sum/2;    

        visit[0][0]=true;

//结果要是得到左上角的格子数量,只能从最左上角的位置出发得到搜索

        temp1.push_back(grid[0][0]);

        dfs(0,0,grid[0][0]);

    }

    if(res==INT_MAX)//可能没有答案

    cout<<0<<endl;

    else

    cout<<res<<endl;

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值