1. 程式人生 > 其它 >資料結構_最小表示法

資料結構_最小表示法

技術標籤:資料結構

題意:

1282 時鐘

有N個時鐘,每個時鐘有M個指標,P個刻度。時鐘是圓形的,P個刻度均分整個圓。每個時鐘每個指標指向整數刻度,並且每個時鐘自身指標指向的數字都不同。你可以任意旋轉時鐘的錶盤,但是你不能轉指標。問最後有多少對時鐘可以變成相同的狀態。

例如:N = 5,M = 2,P = 4,5個時鐘的資料如下{1, 2} {2, 4} {4, 3} {2, 3} {1, 3}
在這裡插入圖片描述
經過旋轉後。 其中(1, 3), (1, 4), (2, 5) 和 (3, 4)是相同的。
在這裡插入圖片描述
給出所有時鐘的資料,求有多少對時鐘是相同的。

輸入
第1行:3個數N, M, P中間用空格分隔,其中N為時鐘的數量,M為錶針的數量,P為刻度的數量(1 <= M, N <= 500, 1 <= P <= 10^9, M <= P)。

第2 - N + 1行:每行M個數,對應一個時鐘,M個指標的位置。

輸出
輸出有多少對時鐘是相同的。

輸入樣例
5 2 4
1 2
2 4
4 3
2 3
1 3

輸出樣例
4

思路:

對於兩個時鐘是否相同,因為只能旋轉錶盤,不能旋轉錶針。。所以我們只需要看看指標之間的差值是否相同就好了。。。最小表示法,返回串s字典序最小的迴圈同構起始位置

最後map記錄一下就好了

程式碼實現:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int a[maxn];
int cha[maxn];
int
ans = 0; map<vector<int> ,int>mp; int n,m,p; int getmin(int s[],int len){//返回最小表示法的始端 int i = 0,j = 1,k = 0; while(i < len&&j < len&&k < len){ int t = s[(i + k) % len] - cha[(j + k) % len]; if(!t) k++; else{ if(t > 0) i += k + 1; else j += k + 1; if
(i == j) j++; k = 0; } } return i < j ? i : j; } void solve(){ sort(a,a + m); for(int i = 1;i < m;i++){ cha[i - 1] = a[i] - a[i - 1]; } cha[m - 1] = a[0] + p - a[m - 1]; int d = getmin(cha,m); vector<int>tmp; tmp.clear(); for(int i = d;i < m;i++) tmp.push_back(cha[i]); for(int i = 0;i < d;i++) tmp.push_back(cha[i]); ans += mp[tmp];//加上之前出現過的相同順序陣列的個數 mp[tmp]++; } int main(){ scanf("%d%d%d",&n,&m,&p); for(int i = 1;i <= n;i++){ for(int j = 0;j < m;j++) scanf("%d",&a[j]); solve(); } printf("%d\n",ans); return 0; }