您的位置:首页 > 其它

Codeforces Round #416 (Div. 2) C. Vladik and Memorable Trip(dp)

2017-05-28 15:28 483 查看
昨天下午看这个题的时候,看了半个多小时没看懂啥意思,第四题也看了半个多小时,没看懂


今天搜了下题解,看懂了。

看懂意思就好说了,dp嘛。然后开始码代码,三重循环筛合法区间,然后dp,超时了。然后想怎么优化,想了一个多小时才想到。。


状态转移方程好找,感觉就难在筛选合法区间。。

dp[i]表示前i个数字的最大值

dp[i] = max{dp[i],{dp[j]+value[j-i]| j >=0 && j <= i}}

#include <stdio.h>
#include <string.h>
#include <set>
#include <algorithm>
using std::max;
using std::set;

const int MAXN = 5010;
int num[MAXN];
int cnt[MAXN];//记录每个数字在整个数组中出现的次数
bool vis[MAXN];
int G[MAXN][MAXN];
int dp[MAXN];

int main()
{
int n;
scanf("%d",&n);
for(int i = 1; i <= n; ++i)
{
scanf("%d",&num[i]);
cnt[num[i]]++;
}
memset(G,-1,sizeof(G));
int sum = 0;
int temp = 0;
for(int i = 1; i <= n; ++i)
{
sum = 0;
temp = 0;
memset(vis,0,sizeof(vis));
for(int j = i; j <= n; ++j)
{
if(!vis[num[j]])
{
vis[num[j]] = true;
sum += cnt[num[j]];
temp ^= num[j];
}
//如果这段区间的所有数字个数==这段区间中的每个数字在整个数组中出现次数的和
//那么这段区间就是合法的
if(j-i+1 == sum)
{
G[i][j] = temp;
}
}
}
int res = 0;
for(int i = 1; i <= n; ++i)
{
dp[i] = dp[i-1];
for(int j = 0; j <= i; ++j)
{
if(G[j][i] != -1)
{
dp[i] = max(dp[i],dp[j-1]+G[j][i]);
if(dp[i] > res)
res = dp[i];
}
}
}
printf("%d\n",res);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: