题目主要需要理解的是第二个样例和“包含左上角的分割区可能包含的最小的格子数目”这句话,其实结合第二个样例,意思就是:对第二个样例而言可以输出2也可以输出10,不过题目要求输出包含左上角元素的结果,所以答案是10
思路分析1:
这里我的思路是采用暴力搜索解决,首先确定我们从左上角作为起点开始搜索,其次是枚举需要切割的格子数量,这里因为需要分割成2部分,所以最大我们可以切割的格子数量是n*m-1,最后设定搜索出口是叠加切割的格子元素后是否等于所有格子元素之和的一半即可
因为这里每次需要切割的格子数是从小到大找的,所以得到的答案自然是最小的
#include<iostream>
#include<cstdlib>
#define MAX 15
using namespace std;
int m, n ,all=0;
int map[MAX][MAX];
int visited[MAX][MAX];
int nextt[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
void dfs(int x, int y,int step,int endd, int sum) {//step代表现在已经得到格子数
if (step == endd) {//剪取的格子数够了//endd代表本次搜索需要切割多少格子数
if (all - sum == sum) { //sum代表已经切割格子元素之和
cout << endd << endl;
exit(0);
}
}
else {
for (int i = 0; i < 4; i++) {
int tx = x + nextt[i][0];
int ty = y + nextt[i][1];
if (tx < 0 || ty < 0 || tx == n || ty == m || visited[tx][ty]) {
continue;
}
visited[tx][ty] = true;
dfs(tx, ty, step + 1, endd, sum + map[tx][ty]);
visited[tx][ty] = false;
}
}
}
int main()
{
int sum;
cin >> m >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> map[i][j];
all += map[i][j];
}
}
sum = n * m - 1;
for (int i = 1; i <= sum; i++) {//枚举每次剪取的格子数
memset(visited, false, sizeof(visited));
visited[0][0] = true;
dfs(0, 0,1, i,map[0][0]);//(0,0)每次都从左上角开始
}
cout << 0 << endl;
return 0;
}
下面是我看到的另外一篇比较好的题解,分享一下
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};
int n,m,sum,minn=INT_MAX,a[15][15];
bool vis[15][15],flag;
inline bool check(int x,int y){return x>0&&x<=m&&y>0&&y<=n;}//特判要注意了,我就在这里被坑了
inline void dfs(int x,int y,int cnt,int now){
if((now<<1)==sum)minn=min(minn,cnt);//取最小值
else if((now<<1)>sum);//已经大于就不用搜了,小优化
else{
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];//向四个方向搜索
if(check(nx,ny)){
if(!vis[nx][ny]){
vis[nx][ny]=1;
dfs(nx,ny,cnt+1,now+a[nx][ny]);
vis[nx][ny]=0;//记得回溯
}
}
}
}
}
signed main(){
cin>>n>>m;
vis[1][1]=1;
for(int i=1;i<=m;i++)for(int j=1;j<=n;j++)cin>>a[i][j],sum+=a[i][j];
dfs(1,1,1,a[1][1]);
if(minn^INT_MAX)cout<<minn<<endl;
else puts("0");//无解
return 0;
}