"Algorithm Competition · 300 Quick Questions" one question per day: "window"

" Algorithm Competition: 300 Quick Questions " will be published in 2024, and it is an auxiliary workbook for "Algorithm Competition" .
All questions are placed in the self-built OJ New Online Judge .
The codes are provided in C/C++, Java, and Python. The topics are mainly low-to-medium level, suitable for beginners and advanced.


" Windows ", link: http://oj.ecustacm.cn/problem.php?id=1706

topic description


[Title Description] There is a photo of a dormitory window, please judge how many different styles of windows there are.   Please judge how many windows of different styles there are according to the input picture. [Input format] The first line of input contains two positive integers n, m (1≤n, m≤120). Next n lines, m characters in each line represent the size of the input image. 【Output Format】 Output a number to represent the answer. 【Input sample】











9 21
#####################
#...+#++++#+...#..+.#
#..+.#.++.#.+..#..+.#
#.+..#....#..+.#..+.#
#####################
#.+..#....#..+.#.+..#
#..+.#.++.#.+..#.+..#
#...+#++++#+...#.+..#
#####################

【Example of output】

4

answer

  This question is a more detailed simulation question. There are two main tasks: one is to deal with the rotation of the window, and the other is to judge the weight.
  (1) The rotation of the window. After each window is read, use Rotate() to rotate it 4 times. After each rotation, it is converted into a string now, and the window is represented by the smallest now, so that the 4 rotations of this window are uniquely determined.
  (2) Severe judgment. The following code cleverly uses set to automatically complete the weight judgment. Insert all windows into set win, and automatically complete the weight judgment function. Finally win.size() is the number of different windows.
  See Notes for details.
[Notes] Use this question to familiarize yourself with the application of set .

  QQ group friends "fleeing against the backlight" made a similar analysis:
insert image description here

C++ code

#include<bits/stdc++.h>
using namespace std;
int n, m;                     //照片的长、宽
char w[125][125];             //窗户照片
char s[125][125];             //一个窗户
void Rotate(int a, int b){
    
        //把窗户s转90度
    char tmp[125][125];
    for(int i=1; i<=a; i++)
        for(int j=1; j<=b; j++)
            tmp[i][j] = s[i][j];
    for(int i=1; i<=a; i++)
        for(int j=1; j<=b; j++)
            s[j][a+1-i] = tmp[i][j];
}
string check(int x1, int y1){
    
                //将左上角坐标为(x1,y1)的窗户变成一个字符串
    int x2=x1, y2=y1;                    //找到窗户右下角坐标(x2, y2)
    while(x2+1<=n && w[x2+1][y1]!='#')  x2++;
    while(y2+1<=m && w[x1][y2+1]!='#')  y2++;
    for(int i=x1; i<=x2; i++)            //将窗户拷贝到s中
        for(int j=y1; j<=y2; j++)
            s[i-x1+1][j-y1+1] = w[i][j];
    string ans;
    int a=x2-x1+1, b=y2-y1+1;            //窗户长a、宽b
    for(int t=1;t<=4;t++){
    
                   //旋转4次
        string now;
        for(int i=1; i<=a; i++)          //把这个二维的窗户转换为一个字符串now
            for(int j=1; j<=b; j++)
                now += s[i][j];
        if(ans.size()==0 || now<ans)  ans=now;    //用其中最小的字符串表示这个窗户
        Rotate(a, b);                   //旋转90度
        swap(a, b);                     //旋转后注意交换长、宽
    }
    return ans;                         //返回一个窗户,用它的4种旋转的最小字符串表示
}
int main(){
    
    
    cin>>n>>m;
    for(int i=1; i<=n; i++)  cin>>(w[i]+1);   //读窗户照片
    set<string> win;                          //win记录所有的窗户,并用set判重
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)               //定位一个窗户,即左上,左、上都是‘#’
            if(w[i-1][j-1]=='#' && w[i][j-1]=='#' && w[i-1][j]=='#')
                win.insert(check(i, j));      //插入一个新窗户,用set判重
    cout<<win.size()<<endl;                   //win.size()就是不同窗户的数量
    return 0;
}

java code

import java.util.*;
public class Main {
    
    
    static int n, m;                               //照片的长、宽 
    static char[][] w = new char[125][125];        //窗户照片    
    static char[][] s = new char[125][125];        //一个窗户
    static void Rotate(int a, int b) {
    
                 //把窗户s转90度
        char[][] tmp = new char[125][125];
        for (int i = 1; i <= a; i++)
            for (int j = 1; j <= b; j++)            
                tmp[i][j] = s[i][j];
        for (int i = 1; i <= a; i++)
            for (int j = 1; j <= b; j++)            
                s[j][a + 1 - i] = tmp[i][j];
    }
    static String check(int x1, int y1) {
    
               //将左上角坐标为(x1,y1)的窗户变成一个字符串 
        int x2 = x1, y2 = y1;                       //找到窗户右下角坐标(x2, y2)   
        while (x2 + 1 <= n && w[x2 + 1][y1] != '#')      x2++;
        while (y2 + 1 <= m && w[x1][y2 + 1] != '#')      y2++;
        for (int i = x1; i <= x2; i++)              //将窗户拷贝到s中
            for (int j = y1; j <= y2; j++)            
                s[i - x1 + 1][j - y1 + 1] = w[i][j];
        String ans = "";
        int a = x2 - x1 + 1, b = y2 - y1 + 1;        //窗户长a、宽b     
        for (int t = 1; t <= 4; t++) {
    
                   //旋转4次   
            String now = "";
            for (int i = 1; i <= a; i++)             //把这个二维的窗户转换为一个字符串now
                for (int j = 1; j <= b; j++)                
                    now += s[i][j];
            if (ans.length() == 0 || now.compareTo(ans) < 0) 
ans = now;                            //用其中最小的字符串表示这个窗户
            Rotate(a, b);                             //旋转90度            
            int temp = a;                             //旋转后注意交换长、宽
            a = b;
            b = temp;                    
        }
        return ans;                                //返回一个窗户,用它的4种旋转的最小字符串表示                
    }
    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= n; i++) w[i] = (" " + sc.next()).toCharArray();    //读窗户照片
        Set<String> win = new HashSet<>();        //win记录所有的窗户,并用set判重                     
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)          //定位一个窗户,即左上,左、上都是‘#’    
                if (w[i - 1][j - 1] == '#' && w[i][j - 1] == '#' && w[i - 1][j] == '#')    
                    win.add(check(i, j));         //插入一个新窗户,用set判重
        System.out.println(win.size());           //win.size()就是不同窗户的数量
    }
}

Python code

n, m = map(int, input().split())                #照片的长、宽
w = [[''] * 125 for _ in range(125)]            #窗户照片
s = [[''] * 125 for _ in range(125)]            #一个窗户
def Rotate(a, b):                               #把窗户s转90度
    tmp = [[''] * 125 for _ in range(125)]
    for i in range(1, a + 1):
        for j in range(1, b + 1):
            tmp[i][j] = s[i][j]
    for i in range(1, a + 1):
        for j in range(1, b + 1):
            s[j][a + 1 - i] = tmp[i][j] 
def check(x1, y1):                               #将左上角坐标为(x1,y1)的窗户变成一个字符串
    x2, y2 = x1, y1                              #找到窗户右下角坐标(x2, y2)
    while x2 + 1 <= n and w[x2 + 1][y1] != '#':  x2 += 1
    while y2 + 1 <= m and w[x1][y2 + 1] != '#':  y2 += 1
    for i in range(x1, x2 + 1):                  #将窗户拷贝到s中
        for j in range(y1, y2 + 1):
            s[i - x1 + 1][j - y1 + 1] = w[i][j]
    ans = ""
    a, b = x2 - x1 + 1, y2 - y1 + 1                 #窗户长a、宽b
    for t in range(1, 5):                           #旋转4次
        now = ""
        for i in range(1, a + 1):                   #把这个二维的窗户转换为一个字符串now
            for j in range(1, b + 1):
                now += s[i][j]
        if len(ans) == 0 or now < ans:   ans = now   #用其中最小的字符串表示这个窗户
        Rotate(a, b)                                 #旋转90度
        a, b = b, a                                  #旋转后注意交换长、宽
    return ans                                       #返回一个窗户,用它的4种旋转的最小字符串表示
for i in range(1, n + 1):   w[i][1:] = input()       #读窗户照片
win = set()                                          #win记录所有的窗户,并用set判重
for i in range(1, n + 1):
    for j in range(1, m + 1):                        #定位一个窗户,即左上,左、上都是‘#’
        if w[i - 1][j - 1] == '#' and w[i][j - 1] == '#' and w[i - 1][j] == '#':
            win.add(check(i, j))                     #插入一个新窗户,用set判重
print(len(win))                                      #len(win)就是不同窗户的数量

Guess you like

Origin blog.csdn.net/weixin_43914593/article/details/131699593