蓝桥杯2014年c组真题1.剪格子 dfs

93 阅读2分钟

视频解析 1.剪格子 - 蓝桥云课 (lanqiao.cn)

2013年C++C组题10_哔哩哔哩_bilibili

这道题我们不能去枚举从哪条边开始剪,地图最大是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;
}