Alex doesn't like boredom. That's why whenever he gets bored, he comes up with games. One long winter evening he came up with a game and decided to play it.
Given a sequence a consisting of n integers. The player can make several steps. In a single step he can choose an element of the sequence (let's denote it ak) and delete it, at that all elements equal to ak + 1 and ak - 1 also must be deleted from the sequence. That step brings ak points to the player.
Alex is a perfectionist, so he decided to get as many points as possible. Help him.
The first line contains integer n (1 ≤ n ≤ 105) that shows how many numbers are in Alex's sequence.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 105).
Print a single integer — the maximum number of points that Alex can earn.
2 1 2
2
3 1 2 3
4
9 1 2 1 3 2 2 2 2 3
10
Consider the third test example. At first step we need to choose any element equal to 2. After that step our sequence looks like this [2, 2, 2, 2]. Then we do 4 steps, on each step we choose any element equals to 2. In total we earn 10 points.
思路:首先我们用一个数组记录每个数对应的总和(因为取它就把它所有的都取了),然后我们设dp[ i ]表示考虑当前值为i以前的所有值所能获得的最大值,那么如果i-1取了,那么删去i,即dp[i] = dp[i -1];如果没取i-1,取i, 那么dp[i] =dp[i - 2] + a[ i ] ,即最后dp[ i ]=max( dp[i - 1], dp[i - 2] + a[ i ]),详见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=100000+100;
int n;
ll a[MAXN],dp[MAXN];
int main()
{
while(~scanf("%d",&n)){
int x,m=0;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++){
scanf("%d",&x);
a[x]+=x; m=max(m,x);
}
dp[0]=0; dp[1]=a[1];
for(int i=2;i<=m;i++)
dp[i]=max(dp[i-1],dp[i-2]+a[i]);
printf("%I64d\n",dp[m]);
}
return 0;
}
思路:trie+博弈。对于每一局博弈结果分为四种状态: 0表示对手可以决定是赢是输,1表示只先者能失败,2表示先者只能赢,3表示先者可以决定胜败。 详见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=100000+100;
const int sigma_size=26;
char s[MAXN];
int n,k,sz;
struct node
{
int st;
node *next[sigma_size];
}*root,trie[MAXN];
struct TRIE
{
node *newnode(){
for(int i=0;i<sigma_size;i++)
trie[sz].next[i]=NULL;
trie[sz].st=0;
return &trie[sz++];
}
void init(){
sz=0;
root=newnode();
}
void insert(char *str){
node *p=root;
int len=strlen(str);
for(int i=0;i<len;i++){
int k=str[i]-'a';
if(p->next[k]==NULL)
p->next[k]=newnode();
p=p->next[k];
}
}
}Trie;
int dfs(node *p){
int& ans=p->st;
int flag=1; ans=0; //flag=1,表示从该点走出去的下一步为必败态
for(int k=0;k<sigma_size;k++){
if(p->next[k]){
flag=0; ans|=dfs(p->next[k]);
}
}
if(flag)
ans=1;
return 3-ans;
}
int main()
{
//freopen("text.txt","r",stdin);
while(~scanf("%d%d",&n,&k)){
Trie.init();
for(int i=0;i<n;i++){
scanf("%s",s);
Trie.insert(s);
}
dfs(root);
int st=trie[0].st;
if(st<2)
printf("Second\n");
else if(st == 2){
if(k&1) printf("First\n");
else printf("Second\n");
}
else
printf("First\n");
}
return 0;
}