视频解析 1.剪格子 - 蓝桥云课 (lanqiao.cn)
这道题我们不能去枚举从哪条边开始剪,地图最大是10*10的地图,这个量太大了。
这道题我们可以转化为四联通问题(剪格子只能一刀,所以是连续的),就是从左上角开始(题目要求的),朝上下左右四个方向走,每次都会走出一条路径来,走过的路径我们不再走,我们统计一下走的路径上的格子的总和,发现有大于整个地图总和的一半时,这条路径就是非法路径,不再走了。
如果这条路径 上格子的总和刚好等于 整个地图总和的一半,这个时候就可以返回了。(隐含回溯)最后让我们求一下最短路径。
如果说在走的过程中,sum已经大于了地图总和,那也可以返回了(剪枝)
因此我们发现这是一个 dfs+回溯+剪枝的模型。
dfs
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
int m,n;
int g[10][10];
int total,ans=100;
int vis[10][10];
void dfs(int i,int j,int sum,int cnt)
{
//递归结束条件
if(sum>total/2)return; //剪枝
if(sum==total/2)
{
ans=min(ans,cnt); //记录最小路径的格子数
return;
}
vis[i][j]=1; //标记已经走过
//四联通
if(i+1<n&&vis[i+1][j]==0)dfs(i+1,j,sum+g[i][j],cnt+1); //往下走
if(i-1>=0&&vis[i-1][j]==0)dfs(i-1,j,sum+g[i][j],cnt+1); //往上走
if(j+1<m&&vis[i][j+1]==0)dfs(i,j+1,sum+g[i][j],cnt+1); //往右走
if(j-1>=0&&vis[i][j-1]==0)dfs(i,j-1,sum+g[i][j],cnt+1); //往左走
vis[i][j]=0; //回溯
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;++i)
{
for(int j=0;j<m;++j)
{
scanf("%d",&g[i][j]);
total+=g[i][j];
}
}
dfs(0,0,0,0);
printf("%d",ans);
return 0;
}