1. 程式人生 > >今日頭條2018校招演算法方向--手串問題

今日頭條2018校招演算法方向--手串問題

題目:

作為一個手串藝人,有金主向你訂購了一條包含n個雜色串珠的手串——每個串珠要麼無色,要麼塗了若干種顏色。為了使手串的色彩看起來不那麼單調,金主要求,手串上的任意一種顏色(不包含無色),在任意連續的m個串珠裡至多出現一次(注意這裡手串是一個環形)。手串上的顏色一共有c種。現在按順時針序告訴你n個串珠的手串上,每個串珠用所包含的顏色分別有哪些。請你判斷該手串上有多少種顏色不符合要求。即詢問有多少種顏色在任意連續m個串珠中出現了至少兩次。
 

輸入描述:

第一行輸入n,m,c三個數,用空格隔開。(1 <= n <= 10000, 1 <= m <= 1000, 1 <= c <= 50) 接下來n行每行的第一個數num_i(0 <= num_i <= c)表示第i顆珠子有多少種顏色。接下來依次讀入num_i個數字,每個數字x表示第i顆柱子上包含第x種顏色(1 <= x <= c)

輸出描述:

一個非負整數,表示該手鍊上有多少種顏色不符需求。

示例1

輸入

5 2 3
3 1 2 3
0
2 2 3
1 2
1 3

輸出

2

說明

第一種顏色出現在第1顆串珠,與規則無衝突。
第二種顏色分別出現在第 1,3,4顆串珠,第3顆與第4顆串珠相鄰,所以不合要求。
第三種顏色分別出現在第1,3,5顆串珠,第5顆串珠的下一個是第1顆,所以不合要求。
總計有2種顏色的分佈是有問題的。 
這裡第2顆串珠是透明的。

解題思路:

假設所有顏色初始時都是合格的。

遍歷所有珠子。對於每一個顏色,若是第一次出現,記錄下初始位置和當前的位置。若某一顏色不是第一次出現,則判斷該顏色當前位置和上一次出現的位置之間的距離是否小於m。若小於m,則這個顏色標記為不合格,並在接下來的迴圈中不再考慮這個顏色,否則,說明該顏色合格,更新該顏色當前的位置為當前珠子。

因為手串為環狀,所以在迴圈最後,要繼續判斷合格的顏色中,距離第一次出現的位置的距離是否小於m。

若顏色為無色,不計入不合要求的顏色中

#include<iostream>
using namespace std;
int main(){
    int n,m,c;
    int count;
    scanf("%d %d %d",&n,&m,&c);
    int color_init_add[c+1];//顏色初始位置
    int color_add[c+1];//顏色位置
    int flag[c+1];//顏色是否合格
    for(int i=1;i<=c;i++){
        color_init_add[i] = -1;
        color_add[i] = -1;
        flag[i] = 1;//初始時顏色都合要求
    }
    int k;
    for(int i=1;i<=n;i++){
        cin>>count;
        for(int j=0;j<count;j++)
        {
            cin>>k;
            if(flag[k]==1){
                if(color_init_add[k] == -1) color_init_add[k] = i;
                if(color_add[k] == -1) color_add[k] = i;
                else{
                    if(i-color_add[k]<m)
                        flag[k] = -1;
                    else
                        color_add[k] = i;
                }
            }
        }
    }
    for(int j=1;j<=c;j++){
        if(flag[j] == 1){
            if(n-color_add[j]+color_init_add[j]<m)
                flag[j] = -1;
        }
    }
    int sum = 0;
    for(int i=1;i<=c;i++){
        if(flag[i] == -1)
            sum++;
    }
    cout<<sum;
    return 0;
}