ACM: NBUT 1105 多连块拼图 - 水题 - 模拟

NBUT 1105  多连块拼图

Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:

Practice

Appoint description: 
System Crawler  (Aug 12, 2016 9:32:14 AM)

Description

多连块是指由多个等大正方形边与边连接而成的平面连通图形。

-- 维基百科

给一个大多连块和小多连块,你的任务是判断大多连块是否可以由两个这样的小多连块拼成。小多连块只能平移,不能旋转或者翻转。两个小多连块不得重叠。左下图是一个合法的拼法,但右边两幅图都非法。中间那幅图的问题在于其中一个小多连块旋转了,而右图更离谱:拼在一起的那两个多连块根本就不是那个给定的小多连块(给定的小多连块画在右下方)。

Input

输入最多包含20组测试数据。每组数据第一行为两个整数n和m(1<=m<=n<=10)。以下n行描述大多连块,其中每行恰好包含n个字符*或者.,其中*表示属于多连块,.表示不属于。以下m行为小多连块,格式同大多连块。输入保证是合法的多连块(注意,多连块至少包含一个正方形)。输入结束标志为n=m=0。

Output

对于每组测试数据,如果可以拼成,输出1,否则输出0。

Sample Input

4 3
.**.
****
.**.
....
**.
.**
...
3 3
***
*.*
***
*..
*..
**.
4 2
****
....
....
....
*.
*.
0 0

Sample Output

1
0
0
/*/
中文题:

模拟题,模拟去用n个完全相同小块覆盖大块。

仔细想一下啊,用小块能够覆盖掉大块的话有且只有一种覆盖方式,而且大块某个点只能由小块的某点覆盖。

这样就简单了,我的做法用,先找从速往下到小块的第一个*号,然后DFS搜一下整个小块的以第一个*为【0,0】的所有坐标。

然后到大块里面去找,从上往下找到第一个*,把小块的每一个坐标覆盖过的位 置全部该成 ‘.’ 记录下一共改了多少个点【前面记录大块一共有多少个点】。

如果相同就说明成功覆盖,否则不能。

AC代码
/*/
#include"algorithm"
#include"iostream"
#include"cstring"
#include"cstdlib"
#include"cstdio"
#include"string"
#include"vector"
#include"queue"
#include"cmath"
#include"map"
using namespace std;
typedef long long LL ;
#define memset(x,y) memset(x,y,sizeof(x))
#define memcpy(x,y) memcpy(x,y,sizeof(x))
#define FK(x) cout<<"["<<x<<"]\n"
#define bigfor(T)  for(int qq=1;qq<= T ;qq++)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

struct Box {
	int x,y;
	Box(int xx,int yy):x(xx),y(yy) {};
	Box() {};
} into[123];

int n,m;
int num2,num;
int erear;
char maps[20][20],box[20][20],sox[20][20],vis[20][20];
int dir[4][2]= {{0,1},{1,0},{-1,0},{0,-1}};

void init() {
	erear=0;
	memset(vis,0);
}
void DFS(int x,int y,int tox,int toy) {
	if(!vis[x][y]) {
		vis[x][y]=1;
		into[erear++]=Box(tox,toy);//记录box的覆盖坐标
		for(int i=0; i<4; i++) {
			int xx=x+dir[i][0];
			int yy=y+dir[i][1];
			if(xx<0||yy<0||xx>=m||yy>=m)continue;
			if(box[xx][yy]!=‘*‘)continue;
			if(vis[xx][yy])continue;
			DFS(xx,yy,tox+dir[i][0],toy+dir[i][1]);
		}
	}
}

int main() {
	while(~scanf("%d%d",&n,&m)) {
		if(!n&&!m)break;
		num=0;
		num2=0;
		for(int i=0; i<n; i++) {
			scanf("%s",maps[i]);
			for(int j=0; j<n; j++) {
				if(maps[i][j]==‘*‘)num++;
			}
		}
		for(int i=0; i<m; i++) {
			scanf("%s",box[i]);
			for(int j=0; j<m; j++) {
				if(box[i][j]==‘*‘)num2++;
			}
		}
		if(num%num2) {
			puts("0");
			continue;
		}
		int stx,sty;
		int flag=1;
		init();
		for(int i=0; i<m; i++) {
			for(int j=0; j<m; j++) {
				if(box[i][j]==‘*‘) {
					DFS(i,j,0,0);
					flag=0;
				}
				if(!flag)break;
			}
			if(!flag)break;
		}

//		for(int i=0;i<erear;i++){
//			cout<<"x "<<into[i].x<<" y "<<into[i].y<<endl;
//		}

		int tot=0;
		flag=0;
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				if(maps[i][j]==‘*‘) {
					for(int k=0; k<erear; k++) {
						if(maps[i+into[k].x][j+into[k].y]!=‘*‘) {//模拟覆盖。
							flag=1;
							break;
						}
						maps[i+into[k].x][j+into[k].y]=‘.‘;
						tot++;
					}
					if(flag)break;
				}
				if(flag)break;
			}
		}
//		puts("");
//		for(int i=0;i<n;i++){
//			puts(maps[i]);
//		}
//		puts("");
		if(tot==num)puts("1");
		else puts("0");
	}
	return 0;
}

  

 
时间: 2024-11-11 06:41:56

ACM: NBUT 1105 多连块拼图 - 水题 - 模拟的相关文章

CodeForces 686A Free Ice Cream (水题模拟)

题意:给定初始数量的冰激凌,然后n个操作,如果是“+”,那么数量就会增加,如果是“-”,如果现有的数量大于等于要减的数量,那么就减掉,如果小于, 那么孩子就会离家.问你最后剩下多少冰激凌,和出走的孩子数量. 析:多水的一个题,就是一个模拟,如果是+,就加上,如果是‘-’,就判断一下,如果不够,就记录下来. 代码如下: #include <iostream> #include <cmath> #include <cstdlib> #include <set>

CodeForces 731B Coupons and Discounts (水题模拟)

题意:有n个队参加CCPC,然后有两种优惠方式,一种是一天买再次,一种是买两天,现在让你判断能不能找到一种方式,使得优惠不剩余. 析:直接模拟,如果本次是奇数,那么就得用第二种,作一个标记,再去计算下一个. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #inclu

CodeForces 723B Text Document Analysis (水题模拟)

题意:给定一行字符串,让你统计在括号外最长的单词和在括号内的单词数. 析:直接模拟,注意一下在左右括号的时候有没有单词.碰到下划线或者括号表示单词结束了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include

CodeForces 342B Xenia and Spies (水题模拟,贪心)

题意:给定 n 个间谍,m个区间,一个 s,一个f,然后从 s开始传纸条,然后传到 f,然后在每个 t 时间在区间内的不能传,问你最少的时间传过去. 析:这个题,就模拟一下就好,贪心策略,能传就传,找好方向,一直传就行,传到 f 就结束. 代码如下: #include <bits/stdc++.h> using namespace std; struct node{ int l, r, t; bool operator < (const node &p) const{ retur

2017.9.10所谓“切题如切菜杯”水题模拟赛(;&#180;д`)ゞ

T1:MHM LGL今天一共要上n节课,这n节课由0标号至n.由于过度劳累,除了第0节课和第n节课,LGL还打算睡上m节课,所以他做了一个睡觉计划表.通过小道消息,LGL得知WQ今天会在学校中检查,所以他想少睡k节课.但是由于某些原因,他又想使相邻的两节睡觉的课之间上的课数量的最小值最大.由于他很困,所以他请你来帮他计算这个值.   输入格式: 第一行为三个整数 n.m.k,接下来的m行为m个整数ai,表示睡觉计划表中LGL想要睡觉的课. 输出格式: 一个整数,表示题目所求的值. 样例输入 样例

CodeForces 339B Xenia and Ringroad(水题模拟)

题意:给定 n 个地方,然后再给 m 个任务,每个任务必须在规定的地方完成,并且必须按顺序完成,问你最少时间. 析:没什么可说的,就是模拟,记录当前的位置,然后去找和下一个位置相差多长时间,然后更新当前位置即可. 代码如下: #include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; typedef long long LL; int main(){ int n, m, x; while(cin >>

20170925“切题如切菜杯”水题模拟赛 第二弹

T1:短 给出一张有n个点和m条双向边的图,要求求出1到n的次短路的长度.一条边可以多次通过. 输入格式: 第一行为两个整数n和m.接下来的m行每行三个整数ai,bi,vi,分别表示这条路连着的两个点和他的长度. 输出格式: 一个整数,表示次短路的长度. 样例输入 样例输出 4 41 2 1002 4 2002 3 2503 4 100 450 样例解释: 最短:1->2->4. 次短:1->2->3->4. 数据范围: 对于 100%的数据:1<=n.vi<=5

Codeforces-Translation(水题)

The translation from the Berland language into the Birland language is not an easy task. Those languages are very similar: a berlandish word differs from a birlandish word with the same meaning a little: it is spelled (and pronounced) reversely. For

HDU 3316 爆搜水题

爆搜水题 模拟扫雷,规则和扫雷一样 给出原图,求在X,Y位置点一下以后的图形,没有弹出的点输出-1,弹出的点输出这个点的数字 从起始点DFS一下即可 #include "stdio.h" #include "string.h" int dir[8][2]={ {-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1} }; int n; int hash[110][110]; char str[110][110]; i