1. 程式人生 > >17年藍橋杯本科B組決賽--對局匹配

17年藍橋杯本科B組決賽--對局匹配

小明喜歡在一個圍棋網站上找別人線上對弈。這個網站上所有註冊使用者都有一個積分,代表他的圍棋水平。

小明發現網站的自動對局系統在匹配對手時,只會將積分差恰好是K的兩名使用者匹配在一起。如果兩人分差小於或大於K,系統都不會將他們匹配。

現在小明知道這個網站總共有N名使用者,以及他們的積分分別是A1, A2, ... AN

小明想了解最多可能有多少名使用者同時線上尋找對手,但是系統卻一場對局都匹配不起來(任意兩名使用者積分差不等於K)?  

輸入

----

第一行包含兩個個整數NK

第二行包含N個整數A1, A2, ... AN。  

對於30%的資料,1 <= N <= 10

對於100%的資料,1 <= N <= 100000, 0 <= Ai <= 100000, 0 <= K <= 100000

輸出

----

一個整數,代表答案。

樣例輸入:

10 0

1 4 2 8 5 7 1 4 2 8

樣例輸出:

6

再比如,

樣例輸入:

10 1

2 1 1 1 1 4 4 3 4 4

樣例輸出:

8

資源約定:

峰值記憶體消耗 < 256M

CPU消耗  < 1000ms

請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。

所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。

注意: main函式需要返回0

注意只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。

注意所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。

提交時,注意選擇所期望的編譯器型別

解題思路:可以對每個積分存在的人數進行計數,按照積分分為k組(k=0時特殊處理),因為不同組的人不會匹配,所以只需要考慮同一組中最多會有多少人不會匹配即可(動態規劃實現)

#include <stdio.h>
#define M 100001
#define max(a,b) a>b?a:b
int score[M]={0};
int search(int k);
int main(void)
{
	int num=0,k=0;
	int i=0,j=0;
	scanf("%d %d",&num,&k);
	for(i=0;i<num;i++)
	{
		scanf("%d",&j);
		score[j]++;
	}
	printf("%d",search(k));
}

int search(int k)
{
	int sum=0;
	int i=0,j=0;
	int val[M]={0},dp[M]={0};
	if(k==0)   //為0時特殊考慮
	{
		for(i=1;i<M;i++)
		{
			if(score[i]) sum++;
		}
	}
	else
	{
		for(i=0;i<k;i++)   //對k組中的每一組進行遍歷
		{
			int m=0;
			for(j=i;j<M;j+=k)  //記錄這一組中的人數分佈情況
			{
				val[m++] = score[j];
			}
			dp[0] = val[0];
			for(j=1;j<m;j++)  //對人數進行動態規劃
			{
				if(j==1) dp[j] = max(dp[0], val[j]);  //0和1不能匹配,因為積分正好相差k
                                else dp[j] = max(dp[j-2] + val[j], dp[j-1]);  //j-2肯定不能和j-1匹配(理由同上),只能和j匹配,j-1也不能和j匹配
			}
			sum+=dp[m-1];  //加上這一組的最大人數
		}
	}
	return sum;
}