首页 > 其他 > 详细

BZOJ1584 USACO 2009 Mar Gold 2.Cleaning Up

时间:2014-09-22 10:24:23      阅读:262      评论:0      收藏:0      [点我收藏+]

题目大意:有长度为N的颜色段,共有m种颜色,要将其划分成若干段,每一段的费用为这一段的不同颜色的数目的平方。求最小总费用。


Sol:

首先我们注意到答案不超过n,因为我们显然可以将每一个划分为一段,答案为n.

于是每一段的颜色总数不超过sqrt(n).

因此我们维护最后出现的sqrt(n)种颜色最后出现的位置,进行转移。

总的时间复杂度为O(n*sqrt(n)).


Code:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
 
#define N 40010
#define M 40010
int col[N], dp[N], seq[210], now[210];
 
#define sqr(x) ((x)*(x))
 
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
     
    register int i, j;
    for(i = 1; i <= n; ++i)
        scanf("%d", &col[i]);
     
    int lim = (int)sqrt(n);
    int nowlen = 0;
     
    int ins;
    for(i = 1; i <= n; ++i) {
        dp[i] = i;
        ins = 0;
        for(j = 1; j <= nowlen; ++j)
            if (seq[j] == col[i]) {
                ins = j;
                break;
            }
        if (!ins) {
            if (nowlen != lim) {
                seq[++nowlen] = col[i];
                now[nowlen] = i;
            }
            else {
                for(j = 1; j < nowlen; ++j)
                    seq[j] = seq[j + 1], now[j] = now[j + 1];
                seq[nowlen] = col[i], now[nowlen] = i;
            }
        }
        else {
            for(j = ins; j < nowlen; ++j)
                seq[j] = seq[j + 1], now[j] = now[j + 1];
            seq[nowlen] = col[i], now[nowlen] = i;
        }
        for(j = nowlen; j >= 2; --j)
            dp[i] = min(dp[i], dp[now[j - 1]] + sqr(nowlen + 1 - j));
    }
     
    printf("%d", dp[n]);
     
    return 0;
}


BZOJ1584 USACO 2009 Mar Gold 2.Cleaning Up

原文:http://blog.csdn.net/wyfcyx_forever/article/details/39471877

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!