目录
文章仅供自学习用 ! ! !
/
文章内容不能保证完全正确.
/
仅供参考
剪格子
describe
如下图所示,3 x 3 的格子中填写了一些整数。
±-–±-+
|10 1|52|
±-***–+
|20|30 1|
*******–+
| 1| 2| 3|
±-±-±-+
我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部
分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0。
Input
程序先读入两个整数 m n 用空格分割 (m,n<10)。
表示表格的宽度和高度。
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000。
output
输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。
Sample Input
3 3
10 1 52
20 30 1
1 2 3
Sample Output
3
Sample Input
4 3
1 1 1 1
1 30 80 2
1 1 1 100
Sample Output
10
解析
模版题目, 使用dfs搜索加上回溯, 加剪枝即可完成.
c++代码
#include<bits/stdc++.h>
using namespace std;
//所有格子的总数
int total;
int row,column;
int g[10][10];
int ans = 100;
//标记数组
int vis[10][10];
void dfs(int i,int j,int sum,int cnt){
//边界判断
if(i<0||j<0||i>=row||j>=column)return;
//如果我没有访问过才会访问
if(vis[i][j])return;
//dfs中止条件
if(sum>total/2)return;
if(sum==total/2){
ans = min(ans,cnt);
return;
}
//标记我来过
vis[i][j]=1;
//4个方向dfs
dfs(i+1,j,sum+g[i+1][j],cnt+1);
dfs(i-1,j,sum+g[i-1][j],cnt+1);
dfs(i,j+1,sum+g[i][j+1],cnt+1);
dfs(i,j-1,sum+g[i][j-1],cnt+1);
//我需要返回上层dfs, 返回后, 我会进行回溯, 将我改变的改变回来
vis[i][j]=0;
}
int main()
{
//录入数据
//题目要求为先录入column
cin>>column>>row;
for(int i=0;i<row;i++){
for(int j = 0;j < column;j++){
scanf("%d",&g[i][j]);
total += g[i][j];
}
}
dfs(0,0,g[0][0],1);
if(ans!=100)cout<<ans<<endl;
if(ans==100)cout<<0<<endl;
return 0;
}
!!!
注意, 本种dfs仅支持一笔画, 不支持在一个点上面, 同时对多个方向dfs, 即T字形的通道
比如本题
3 3
301 1 1
1 100 100
1 100 5
输出结果为0, 而结果显然为5;
但是如上的代码是能够AC的, 所以测试用例不完善.
所以需要更改代码才行.