CF 811C (DP)

http://codeforces.com/problemset/problem/811/C
题意是一群人在坐火车。先告诉你有n个人,然后告诉你n个目的地(用数字表示的)。目的地一样的所有人要么都在一辆列车上,要么就都在原地不要动。在同一辆列车上的舒适度,用^计算。

一开始的思路:
虽起点和终点进行预处理并对这个区间求^值。然后转换成一个背包问题,当时还在网上找到一个叫带权区间调度问题。其实就是背包问题的一个变形。感觉我们想的也挺对的。结果我比较傻。。我预处理就写了五六十行。比赛就结束了,后来看了别人的代码。也没有往下写的欲望了。不过听说直接这样写就TLE了。

正确的思路:
其实也是个变形的背包,扫一遍每个目的地,对于当前的状态有两个转移过来的可能,一个是这个人就原地不动了,另一个状态就是找出这个目的地往前推最短的一个合法区间。(合法区间就是这个区间中要么就不要某个目的地,要么就包括了所有要去这个目的地的人)。因为加法肯定要比异或要好吧。所以只找出最短的就可以了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=5005;
int sum[maxn];
int num[maxn];
int a[maxn];
int dp[maxn];
int main(){
    int n,xors,p,q;
    cin>>n;
    memset(dp,0,sizeof(dp));
    memset(a,0,sizeof(a));
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum[a[i]]++;//sum记录每个目的地的总人数。
    }
    for(int i=1;i<=n;i++){
        dp[i]=dp[i-1];
        memset(num,0,sizeof(num));
        xors=p=q=0;//p是记录有几个目的地的人已经进入区间。q记录有几个进入区间的目的地的所有人已经找完了
        for(int j=i;j>=1;j--){
            if(num[a[j]]==0){
                xors^=a[j];
                p++;
            }
            num[a[j]]++;
            if(num[a[j]]==sum[a[j]]){
                q++;
            }
            if(p==q){//找到了最短的合法区间
                dp[i]=max(dp[i-1],dp[j-1]+xors);
                break;
            }
        }       
    }
    printf("%d\n",dp[n]);
    return 0;
}
/*
9
5 1 3 1 5 2 4 2 5
0 2 3
3 3 2
0 6 4
4 7 6
6 8 1
6
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值