資料結構_最小表示法
阿新 • • 發佈:2020-12-12
技術標籤:資料結構
題意:
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)。
輸出
輸出有多少對時鐘是相同的。
輸入樣例
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;
}