時間限制: 10000ms 單點時限: 1000ms 記憶體限制: 256MB
描述
小Hi和小Ho在玩一個遊戲。給定一個數組A=[A1, A2, ... AN],小Hi可以指定M個不同的值S1,S2, S3 ... SM,這樣他的總得分是 ΣSi × count(Si)。(count(Si)是數組中與Si相等的元素的個數)。
為了增加難度,小Ho要求小Hi選擇的S1..SM其中任意兩個Si和Sj都滿足|Si-Sj| > 1。
你能協助小Hi算出他最大得分是多少嗎。 輸入
第一行包含兩個整數N和M。
第二行包含N個整數A1, A2, ... AN。
對於30%的資料,1 ≤ M ≤ N ≤ 10
對於100%的資料,1 ≤ M ≤ N ≤ 1000 1 ≤ Ai ≤ 100000 輸出
最大得分 範例輸入
5 2 1 2 1 2 3
範例輸出
5
題解: 先把輸入的內容hash一下到一個vector裡,這個vector裡每個點存一下Ai的值和出現的次數,是按照Ai的值大小排序的。 然後對於每個Vector裡的結點,想象成一個背包。 dp[i][j]是代表從前i個背包裡取j個所能拿到的最大值 因為|Si-Sj| > 1,所以如果前一個背包和當前的背包值的大小剛好差了1,那麼就要跳過上一個背包來更新當前的值。 不然,就直接更新就好。
#include <iostream>#include <stdio.h>#include <math.h>#include <stdlib.h>#include <string>#include <string.h>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <stack>#include <bits/stdc++.h>using namespace std;int T;int x,y,a,b;int N,M;int A[1009];int V[100009];int dp[1009][1009];//前i個包裡拿走j個struct node{ int V,C; node(){} node(int v,int c){ V=v; C=c; }};int main(){ cin>>N>>M; memset(V,0,sizeof(V)); int maxV=-1; for(int i=0;i<N;i++){ scanf("%d",&A[i]); V[A[i]]++; maxV=max(maxV,A[i]); } vector<node>nums; nums.push_back(node(0,0)); for(int i=1;i<=maxV;i++){ if(V[i]!=0)nums.push_back(node(i,V[i])); } int numOfBags=nums.size()-1; memset(dp,0,sizeof(dp)); for(int i=1;i<=M;i++)dp[1][i]=nums[1].V*nums[1].C; for(int i=2;i<=numOfBags;i++){ for(int j=1;j<=M;j++){ if(nums[i].V-nums[i-1].V>1){ dp[i][j]=max(dp[i-1][j-1]+nums[i].V*nums[i].C,dp[i-1][j]); } else{ dp[i][j]=max(dp[i-2][j-1]+nums[i].V*nums[i].C,dp[i-1][j]); } } } cout<<dp[numOfBags][M]<<endl; return 0;}//// _oo0oo_// o8888888o// 88" . "88// (| -_- |)// 0\ = /0// ___/`---'\___// .' \\| |// '.// / \\||| : |||// \// / _||||| -:- |||||- \// | | \\\ - /// | |// | \_| ''\---/'' |_/ |// \ .-\__ '-' ___/-. /// ___'. .' /--.--\ `. .'___// ."" '< `.___\_<|>_/___.' >' "".// | | : `- \`.;`\ _ /`;.`/ - ` : | |// \ \ `_. \_ __\ /__ _/ .-` / /// =====`-.____`.___ \_____/___.-`___.-'=====// `=---='////// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//// 佛祖保佑 永無BUG//////