《算法竞赛·快冲300题》每日一题:“ 盲文文字编码”

算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。

文章目录

  • 题目描述
  • 题解
  • C++代码
  • Java代码
  • Python代码

盲文文字编码” ,链接: http://oj.ecustacm.cn/problem.php?id=2141

题目描述

【题目描述】 盲文文字编码由一些凸起的点组成。
  如下图所示,我们使用坐标 (0,2),(1,1)表示左侧盲文文字,用坐标(0,1)(1,0)表示右侧盲文文字。
《算法竞赛·快冲300题》每日一题:“ 盲文文字编码”_第1张图片
  注意:左右图可以通过平移得到,因此被认为是统一文字编码。
  现在给你 n 个文字,请判断存在多少个不同的文字。
【输入格式】 输入第一行为正整数 n,表示存在 n 个文字,1≤n≤100000。
  接下来存在 n 部分,每部分第一行为正整数 m ,表示这个文字由 m 个点组成1≤m≤1000。
  接下来m行,每行包含两个整数 x 和 y,-1000≤x,y≤1000。
  输入保证总点数不超过1000000。
【输出格式】 输出一个整数表示答案。
【输入样例】

样例1:
2
2
0 2
1 1
2
0 1
1 0

样例22
3
-1 0
0 1
1 0
3
-1 0
0 -1
1 0

【输出样例】

样例1:
1

样例22

题解

  题意是,如果一个图案中的黑点通过平移能到达另一个图案,那么这两个图案就是一样的。由于只需要平移,不需要旋转,处理比较简单。只需要把所有图案的左下角黑点都平移到原点,即可判断有多少不同的图案。
  图案的左下角平移到原点后,这个图案的其他点也平移到相应的位置。具体操作是把图案的所有坐标排序,找到左下角的点P,平移到原点,其他点的坐标减去P的坐标得到新坐标。把每个图案的所有坐标存到vector中;对所有图案用set判重。

【重点】 set的应用。

C++代码

  代码的复杂度:共n个文字,第14行对每个文字排序是O(mlogm)的,第18行插入到set是O(logn)的,总复杂度O(n(mlogm+logn))。

#include
using namespace std;
set<vector<pair<int,int>>>tot;
int main(){
    int n;
    scanf("%d", &n);
    while(n--){
        int m;     scanf("%d", &m);
        vector<pair<int,int> >a;      //用vector存一个图案a
        while(m--){                   //读一个图案的m个点
            int x, y;   scanf("%d%d", &x, &y);
            a.push_back(make_pair(x, y));
        }
        sort(a.begin(), a.end()); //把这个图案的m个点排序,先x从小到大,x相同再y从小到大
        int delta_x = a[0].first, delta_y = a[0].second;
        for(auto & x : a)       //把最左下点移到原点,其他点平移到相应位置
            x.first -= delta_x, x.second -= delta_y;
        tot.insert(a);  //插入到set tot中,判重
    }
    cout<<tot.size()<<endl;
    return 0;
}

Java代码

  在使用Set类型时,确保在添加元素之前先正确实现equals()和hashCode()方法,以避免重复元素被添加到集合中。

import java.util.*;
import java.io.*; 
class Main {
    static BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
    public static void main(String[] args) throws IOException {
        Set<List<Point>> tot = new HashSet<>();
        int n = Integer.parseInt(input.readLine().trim());
        for (int i = 0; i < n; i++) {
            int m = Integer.parseInt(input.readLine().trim());
            List<Point> a = new ArrayList<>();
            for (int j = 0; j < m; j++) {
                String[] line = input.readLine().trim().split("\\s+");
                int x = Integer.parseInt(line[0]);
                int y = Integer.parseInt(line[1]);
                a.add(new Point(x, y));
            }
            Collections.sort(a, new PointComparator());
            int delta_x = a.get(0).x;
            int delta_y = a.get(0).y;
            for (int j = 0; j < m; j++) {
                a.get(j).x -= delta_x;
                a.get(j).y -= delta_y;
            }
            tot.add(a);
        }
        System.out.println(tot.size());
    } 
    static class PointComparator implements Comparator<Point> {
        public int compare(Point p1, Point p2) {
            if (p1.x != p2.x) return p1.x - p2.x;
            else              return p1.y - p2.y;
        }
    }
 
    static class Point {
        int x, y;
        Point(int x, int y) {
            this.x = x;
            this.y = y;
        } 
        @Override
        public boolean equals(Object obj) {
            if (this == obj)  return true;            
            if (obj == null || getClass() != obj.getClass()) 
                return false;
            Point point = (Point) obj;
            return x == point.x && y == point.y;
        }
        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }
    }
}

Python代码

from functools import cmp_to_key
import sys
input = sys.stdin.readline           #加这句后读入会快些
def sort_points(p1, p2):
    if p1[0] != p2[0]:    return p1[0] - p2[0]   #x坐标不等,比较x
    else:                 return p1[1] - p2[1]   #x坐标相等,比较y
tot = set()
n = int(input())
for i in range(n):
    m = int(input())
    a = []
    for j in range(m):
        x, y = map(int, input().split())
        a.append((x, y))
    a.sort(key=cmp_to_key(sort_points))
    delta_x, delta_y = a[0]
    a = [(x - delta_x, y - delta_y) for x, y in a]
    tot.add(tuple(a))
print(len(tot))

你可能感兴趣的:(算法竞赛快冲300题,算法)