1. 程式人生 > >CSU - 1581 Clock Pictures (KMP的變形題,難想到)

CSU - 1581 Clock Pictures (KMP的變形題,難想到)

i++ span pin get medium 思考 col set cloc

題目鏈接:

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1581

題目意思:告訴你現在有兩個鐘,現在兩個鐘上面都有n個指針,告訴你指針的位置,問你將鐘表旋轉的話能不能使得兩個鐘表重合

ps:將鐘面的圓分成360000份,告訴你的指針的位置代表正北方向到指針的夾角(順時針)

分析:

對每個鐘的指針,按照與正北方向的夾角(順時針)(因為題目給的就是順時針)從小到大排序

然後得到相鄰指針間的間距,然後根據KMP跑這些間距,如果能夠匹配成功的話

那麽肯定可以旋轉到重合啊

有幾個需要註意的地方:

1.最後一個指針的角度減去第一個指針的角度然後要加上360000才是兩個指針間的間距

2.因為鐘表是環,所以我們一個鐘表的數組要變成兩倍長度的該數組,因為我們要模擬環的匹配

這個是需要仔細思考的地方!

code:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<memory>
#include<algorithm>
using namespace std;
#define mod 360000
int a[200005],b[200005];
int c[200005],d[200005*2];
int next1[200005];
int sum;
void getnext(int s[],int next1[],int m) { next1[0]=0; next1[1]=0; for(int i=1;i<m;i++) { int j=next1[i]; while(j&&s[i]!=s[j]) j=next1[j]; if(s[i]==s[j]) next1[i+1]=j+1; else next1[i+1]=0; } }
int kmp(int ss[],int s[],int next1[],int n,int m) { getnext(s,next1,m); int j=0; for(int i=0;i<n;i++) { while(j&&s[j]!=ss[i]) j=next1[j]; if(s[j]==ss[i]) j++; if(j==m) { return 1; } } return 0; } int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) scanf("%d",&b[i]); sort(a,a+n); sort(b,b+n); for(int i=0;i<n-1;i++) c[i]=a[i+1]-a[i]; c[n-1]=a[0]-a[n-1]+mod; for(int i=0;i<n-1;i++) d[i]=b[i+1]-b[i]; d[n-1]=b[0]-b[n-1]+mod; for(int i=n;i<2*n;i++) d[i]=d[i-n]; if(kmp(d,c,next1,2*n,n)) printf("possible\n"); else printf("impossible\n"); return 0; }

CSU - 1581 Clock Pictures (KMP的變形題,難想到)