最小表示法,以及二维数组的比较方法

雪花雪花雪花 用到的是最小表示法

有N片雪花,每片雪花由六个角组成,每个角都有长度。

第i片雪花六个角的长度从某个角开始顺时针依次记为ai,1,ai,2,…,ai,6。

因为雪花的形状是封闭的环形,所以从任何一个角开始顺时针或逆时针往后记录长度,得到的六元组都代表形状相同的雪花。

例如ai,1,ai,2,…,ai,6和ai,2,ai,3,…,ai,6,ai,1就是形状相同的雪花。

ai,1,ai,2,…,ai,6和ai,6,ai,5,…,ai,1也是形状相同的雪花。

我们称两片雪花形状相同,当且仅当它们各自从某一角开始顺时针或逆时针记录长度,能得到两个相同的六元组。

求这N片雪花中是否存在两片形状相同的雪花。

输入格式
第一行输入一个整数N,代表雪花的数量。

接下来N行,每行描述一片雪花。

每行包含6个整数,分别代表雪花的六个角的长度(这六个数即为从雪花的随机一个角顺时针或逆时针记录长度得到)。

同行数值之间,用空格隔开。

输出格式
如果不存在两片形状相同的雪花,则输出:

No two snowflakes are alike.

如果存在两片形状相同的雪花,则输出:

Twin snowflakes found.

数据范围
1≤n≤100000 ,
0≤ai,j<10000000
输入样例:
2
1 2 3 4 5 6
4 3 2 1 6 5
输出样例:
Twin snowflakes found.

令着几组数,都找到自己字符串字典序最小的表示法,如果有一样的,就是相同的;

	#include<iostream>
	#include<algorithm>
	#include<cstring>
	#include<stdio.h>
	using namespace std;
	const int N=100010;
	int snows[N][6],isnow[6],snow[6],idx[N];
	bool cmp_array(int a[],int b[])
  //与下面的cmp函数一同构成二维数组比较的一个方法。很强
	{   for(int i=0;i<6;i++)
	    if(a[i]>b[i])
	    return false;
	    else if(a[i]<b[i])
	    return  true; 
	    return false;
	}
    bool cmp(int a,int b)
	{
	    return cmp_array(snows[a],snows[b]);
	}
	void get_min(int a[])//最小表示法,找到这个字符串中字典序最小的。比如abca 可以出来很多循环同构的字符串'abca''aabc''caab''bcaa';其中字典序最小的就是aabc,这个就是最小表示法是得到的结果
	{  
	    int n=6;
	    static  int b[12];
	    for(int i=0;i<12;i++)b[i]=a[i%6];//先把要找最小表示法的数组复制一遍到自己的元素组后面,成为b数组。
	     int i=0,j=1,k;
	     while(i<n&&j<n)
	     {
	         for(k=0;k<n&&b[i+k]==b[j+k];k++);//如果i下标和j下标表示的一样的话,就让k增加
	         if(k==n)
	         break;
	         if(b[i+k]>b[j+k]){//如果i下标的数大于j下标的数,那么,i就跳过k个数,另找小的数,因为j下标的数小于i下标的数,i就不能是最小表示法
	             i=i+k+1;
	             if(i==j)
	             i++;
	         }
	         else{
	             j=j+k+1;
	             if(i==j) j++;
	         }
	         
	     }
	     k=min(i,j);//找到最小的下标给
	     for(int i=0;i<6;i++)
	     a[i]=b[i+k];
	     
	}

	int main(){
	    int n;
	  cin>>n;
	  for(int i=0;i<n;i++)
	  {
	      for(int j=0,k=5;j<6;j++,k--)
	      {
	          scanf("%d",&snow[j]);
	           isnow[k]=snow[j];
	      }
	    get_min(snow);
	    get_min(isnow);
	    if(cmp_array(snow,isnow))memcpy(snows[i],snow,sizeof(snow));
	    else memcpy(snows[i],isnow,sizeof(isnow));
	      idx[i]=i; 
	  }
	    sort(idx,idx+n,cmp);//二维数组的大小比较
	    bool flag=false;
	    for(int i=1;i<n;i++)
	    {
	        if(!cmp(idx[i-1],idx[i])&&!cmp(idx[i],idx[i-1]))//如果两个最小表示法得出的数都一样,那么就是有两个雪花一样的
	        {
	            flag=true;
	            break;
	        }
	    }
	    if(flag)puts("Twin snowflakes found.");
	    else
	    puts("No two snowflakes are alike.");
	    return 0;
	    
	}
posted @ 2020-02-06 13:08  arbor_one  阅读(713)  评论(0)    收藏  举报