从大模板中切小模板,求能切出的最大数量

题目描述:有一个MN的材料和一个st的模板,从材料中切除模板,求最大能切出来的模板的数量。
sample input:
3 4
a b c d
c d a b
a c c d
2 2
a b
c d
sample output
2

思路:
定义两个字符数组将这两幅图存储起来
使用一个判断模块儿,当进行搜索的时候,判断该位置是否合法(也就是以该位置为起点的ST图形是否能和输入的ST图形恰好匹配)
构造一个初始化模块儿,当位置合法的时候,可以选择使用或者不使用这种位置
使用深搜模块儿,逐行进行扫描。
如果到某一位置,判断时合法。我们采取两种行动(要么将大图中匹配的位置标记为0,然后继续深度搜索,要么就当什么事都没有发生,继续逐行扫描)采取这两种操作的原因是,我们不知道哪种操作是更好的结果,所以我们就都试试
当该行扫描完之后,进入下一行继续进行扫描。
程序出口是扫描到了最后一行
因为递归过程中遍历了所有的可能,如果遇到更优解,我们需要进行答案的更新。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std; 
#define MAX 1010
char map[MAX][MAX],mapb[MAX][MAX];
char temp[MAX][MAX];//记录中间图的变换,方便在递归中的回溯进行使用 
int M,N,s,t;//分别为这两个图形的长和宽 
int Max,ans;//分别记录每次遍历的最大块儿数和最终答案 
bool judge(char map[][MAX],int i,int j){//传入当前所搜索到的位置 
	int x=i;int y=j;//x来表示行数,y来表示列数 
	for(i=0;i<s;i++)//判断两个图是否匹配 
		for(j=0;j<t;j++)
			if(map[x+i][y+j]!=mapb[i][j])
				return false;
	return true;
}
void init_temp(int x,int y){//将已经遍历过的位置标记 
	for(int i=0;i<M;i++) 
		for(int j=0;j<N;j++)
			temp[i][j]=map[i][j];
	for(int i=0;i<s;i++)
		for(int j=0;j<t;j++)
			temp[x+i][y+j]='0'; 
}
void dfs(char map[][MAX],int x,int y,int Max){
	if(ans<Max)//ans来记录块儿的数量 
		ans=Max;
	if(x>=M){//记录递归出口,走到最后一行就返回 
		return ;
	}
	for(int i=y;i<N;i++){//对x行的每一列都进行搜索
		 if(judge(map,x,i)){//满足判段进行下一步递归 x,i这个位置开始满足小方块
		 	init_temp(x,i);//把map数组复制给temp数组,且吧刚刚的那一块mapb置为0
			dfs(temp,x,i+t,Max+1);//将遍历过的位置标记,然后继续遍历(跳过刚刚裁下来的那块,继续往后遍历)截取这一块的情况
			//dfs完成之后又开始对map的i+1进行遍历,也就是不截取这一块的情况,截取的情况是使用另一个数组,所以没有回溯赋值
			 }	 
	} 
	dfs(map,x+1,0,Max);//遍历下一行
}
int main(){
	cin>>M>>N;
	for(int i=0;i<M;i++)	
		for(int j=0;j<N;j++)
			cin>>map[i][j];
	cin>>s>>t;
	for(int i=0;i<s;i++)
		for(int j=0;j<t;j++)
			cin>>mapb[i][j];
	ans=0;Max=0;
	dfs(map,0,0,0);	
	cout<<ans<<endl;
	cin>>ans;
	return 0;
} 

关键理解:

for(int i=y;i<N;i++){//对x行的每一列都进行搜索
		 if(judge(map,x,i)){//满足判段进行下一步递归 x,i这个位置开始满足小方块
		 	init_temp(x,i);//把map数组复制给temp数组,且吧刚刚的那一块mapb置为0
			dfs(temp,x,i+t,Max+1);//将遍历过的位置标记,然后继续遍历(跳过刚刚裁下来的那块,继续往后遍历)截取这一块的情况
			//dfs完成之后又开始对map的i+1进行遍历,也就是不截取这一块的情况,截取的情况是使用另一个数组,所以没有回溯赋值
			 }	 
	} 
	dfs(map,x+1,0,Max);//遍历下一行

一共两个方案,裁剪的方案使用新的数组来存储,而不选择裁剪的使用原数组。
dfs完成之后开始执行for循环,又开始对map的i+1进行遍历,也就是不截取这一块的情况,截取的情况是使用另一个数组,所以没有回溯赋值

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值