Appearance Analysis UVALive(模拟)

题目链接: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;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值