CF 811C (DP)

来源:互联网 发布:财务部swot矩阵分析表 编辑:程序博客网 时间:2024/05/20 20:03

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;}/*95 1 3 1 5 2 4 2 50 2 33 3 20 6 44 7 66 8 16*/
原创粉丝点击