1. 程式人生 > >2017藍橋杯C++B組 國賽

2017藍橋杯C++B組 國賽

個人理解,僅供參考,歡迎討論
(5)
標題:對局匹配

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

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

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

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

輸入

第一行包含兩個個整數N和K。
第二行包含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 , 不能通過工程設定而省略常用標頭檔案。

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

把不能出現的人連成一條鏈,dp[i][0]表示不選第i個人的最多人數,dp[i][1]表示選第i個人的最多人數,則 dp[[i][0]=max(dp[pre][1],dp[pre][1]), dp[i][1]=dp[pre][0]+a[u];

#include <cstdio>
#include <algorithm>
#include <cstdlib> #include <bits/stdc++.h> typedef long long LL; const int N =1e5+100; using namespace std; typedef long long LL; const LL mod = 1000000009; int a[N], vis[N]; vector<int>p[N]; int ans; int dp[N][3]; void dfs(int u,int pre) { dp[u][1]=a[u]+dp[pre][0]; dp[u][0]=max(dp[pre][1],dp[pre][0]); ans=max(max(dp[u][1],dp[u][0]),ans); vis[u]=1; for(int i=0;i<p[u].size();i++) { int v=p[u][i]; if(!vis[v]) { dfs(v,u); } } return ; } int main() { memset(a,0,sizeof(a)); int n, k; scanf("%d %d", &n, &k); for(int i=1; i<=n; i++) { int x; scanf("%d", &x); a[x]++; } if(k==0) { int num=0; for(int i=1; i<=n; i++) if(a[i]!=0)num++; cout<<num<<endl; } else { for(int i=0;i+k<=100000;i++) { if(a[i]!=0&&a[i+k]!=0) p[i].push_back(i+k),p[i+k].push_back(i); } int num=0; memset(vis,0,sizeof(vis)); memset(dp,0,sizeof(dp)); for(int i=0;i<=100000;i++) { if(a[i]!=0&&vis[i]==0) { ans=0; dfs(i,100001); num+=ans; } } cout<<num<<endl; } return 0; }