Appearance Analysis UVALive(模拟)

xiaoxiao2021-02-28  181

题目链接:https://vjudge.net/problem/UVALive-7747

题意:给定r*w的图,包含若干窗户,每个窗户由“.”或“+”组成,每个窗户大小相等(矩形非正方形),相邻窗户间有“#”间隔开,大矩形的外围也是一圈“#”,求一共有多少种不同的窗户。若一个窗户经过旋转0 90 180 270或360度能与另一个窗户完全重合,则认为这两个窗户是同一种窗户。

思路:我是直接模拟的,先确定窗户的长宽,然后在大矩形中分离出每个窗户,三个get_window函数将其旋转90 180 270度得到它的三种形态,每种窗户储存在set<string>ans中,每个窗户用字符串储存,每次判断该字符串是否在ans中已存在,若该窗户四种形态均不存在,则计数加一,将加入ans中。写的很长,但是很简单明了,缺点也是太长写起来费时间,在场上出的不算太快。

代码如下:

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<cstdlib> #include<sstream> #include<deque> #include<stack> #include<set> #include<map> using namespace std; typedef long long ll; typedef unsigned long long ull; const double eps = 1e-9; const int maxn = 111 + 20; const int maxt = 300 + 10; const int mod = 10; const int dx[] = {1, -1, 0, 0}; const int dy[] = {0, 0, -1, 1}; const int Dis[] = {-1, 1, -5, 5}; const double inf = 0x3f3f3f3f; const int MOD = 1000; const double PI = acos(-1.0); int n, m, k; char g[maxn][maxn];//储存输入的原矩形 set<string> windows;//储存每种窗户 char window[maxn][maxn], window2[maxn][maxn], window3[maxn][maxn], window4[maxn][maxn];//每个窗户的四种形态 int len, wid; int ansnum; string add(){//将窗户转化成字符串形式便于储存 string ans = ""; for(int i = 0; i < len; ++i){ for(int j = 0; j < wid; ++j){ ans += window[i][j]; } } return ans; } string add2(){ string ans = ""; for(int i = 0; i < wid; ++i){ for(int j = 0; j < len; ++j){ ans += window2[i][j]; } } return ans; } string add3(){ string ans = ""; for(int i = 0; i < len; ++i){ for(int j = 0; j < wid; ++j){ ans += window3[i][j]; } } return ans; } string add4(){ string ans = ""; for(int i = 0; i < wid; ++i){ for(int j = 0; j < len; ++j){ ans += window4[i][j]; } } return ans; } void get_window2(){//将原窗户旋转90度 memset(window2, 0, sizeof window2); for(int i = 0; i < wid; ++i){ for(int j = 0; j < len; ++j){ window2[i][j] = window[len - j - 1][i]; } } } void get_window3(){//旋转180度 memset(window3, 0, sizeof window3); for(int i = 0; i < len; ++i){ for(int j = 0; j < wid; ++j){ window3[i][j] = window2[wid - j - 1][i]; } } } void get_window4(){//旋转270度 memset(window4, 0, sizeof window4); for(int i = 0; i < wid; ++i){ for(int j = 0; j < len; ++j){ window4[i][j] = window3[len - j - 1][i]; } } } void judge(){ if(windows.empty()){//碰到的第一个窗户直接加入windows中,其他的都要进行判断了 windows.insert(add()); ++ansnum; return; } string ans1 = add(); if(windows.find(ans1) != windows.end()){//出现过window return; } get_window2();//得到旋转90度后的窗户 string ans2 = add2();//转化成字符串形式便于判断和储存 if(windows.find(ans2) != windows.end()){//出现过window2 return; } get_window3(); string ans3 = add3(); if(windows.find(ans3) != windows.end()){//出现过window3 return; } get_window4(); string ans4 = add4(); if(windows.find(ans4) != windows.end()){//出现过window4 return; } windows.insert(ans1);//四种都没出现过,将其添加到windows中,种类加一 ++ansnum; } int main(){ string s; while(~scanf("%d%d", &n, &m)){ ansnum = 0; windows.clear(); memset(g, 0, sizeof g); for(int i = 0; i < n; ++i){ scanf("%s", g[i]); } len = 0, wid = 0; for(int i = 1; i < n; ++i){ if(g[i][1] != '#') ++len;//每个窗户的长 else break; } for(int j = 1; j < m; ++j){ if(g[1][j] != '#') ++wid;//每个窗户的宽 else break; } memset(window, 0, sizeof window); int x = 1, y = 1, mx = n - len - 1, my = m - wid - 1; int xx, yy; for(x = 1; x < n; x += len + 1){//遍历每一个窗户 for(y = 1; y < m; y += wid + 1){ memset(window, 0, sizeof window); xx = x + len; yy = y + wid; for(int i = x; i < xx; ++i){//将每个窗户从原矩形中分离出来 for(int j = y; j < yy; ++j){ window[i - x][j - y] = g[i][j]; } } judge();//判断是否是新出现的种类 } } printf("%d\n", ansnum);//输出窗户种类数 } return 0; }

转载请注明原文地址: https://www.6miu.com/read-25375.html

最新回复(0)