杭州电子科技大学上机题——切模板

杭州电子科技大学上机题——切模板

题目描述:
有一个MN的材料和一个ST的模板,从材料中切除模板,求最大能切出来的模板数量。
输入:
第一行 M N
下面的M行N列:材料的具体内容
第MM+2行: S T
下面的S行T列:模板材料的具体内容

Sample input:
3 4
a b c d
c d a b
a c c d
2 2
a b
c d
Sample out:
2

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

#include<iostream>
using namespace std;
#define MAX 100
char map[MAX][MAX], mapb[MAX][MAX];
char temp[MAX][MAX];//记录中间图的变换,方便在递归中的回溯进行使用
int M, N, S, T;
int Max, endMax;//分别记录每次遍历的最大块数和最终块数
bool judge(char map[][MAX], int i, int j) {//判断两个图是否匹配
	int x = i;
	int y = j;
	for (i = 0;i < S;i++)
		for (j = 0;j < T;j++)
			if (mapb[i][j] != map[i + x][j + y])
				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 (Max > endMax) {
		endMax = Max;
	}
	if (x >= M)//记录递归出口,走到最后一行就返回
		return;
	for (int i = y;i < N;i++) {//对x行的每一列都进行搜素
		if (judge(map, x, i)) {//满足判断进行下一步递归
			init_temp(x, i);
			dfs(temp, x, i + T, Max + 1);//将遍历过的位置标记,然后继续遍历
		}
	}
	dfs(map, x + 1, 0, Max);
}
int main() {
	Max = 0;
	endMax = 0;
	cout << "输入M*N材料的信息:" << endl;
	cin >> M >> N;
	for (int i = 0;i < M;i++)
		for (int j = 0;j < N;j++)
			cin >> map[i][j];
	cout << "输入S*T材料的信息:" << endl;
	cin >> S >> T;
	for (int i = 0;i < S;i++)
		for (int j = 0;j < T;j++)
			cin >> mapb[i][j];
	dfs(map, 0, 0, 0);
	cout << endMax << endl;
	return 0;
}

运行测试结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值