• HDU 5009 Paint Pearls 双向链表优化DP


    Paint Pearls

    Problem Description
     
    Lee has a string of n pearls. In the beginning, all the pearls have no color. He plans to color the pearls to make it more fascinating. He drew his ideal pattern of the string on a paper and asks for your help. 

    In each operation, he selects some continuous pearls and all these pearls will be painted to their target colors. When he paints a string which has k different target colors, Lee will cost k2 points. 

    Now, Lee wants to cost as few as possible to get his ideal string. You should tell him the minimal cost.
     
    Input
     
    There are multiple test cases. Please process till EOF.

    For each test case, the first line contains an integer n(1 ≤ n ≤ 5×104), indicating the number of pearls. The second line contains a1,a2,...,an (1 ≤ ai ≤ 109) indicating the target color of each pearl.
     
    Output
     
    For each test case, output the minimal cost in a line.
     
    Sample Input
     
    3 1 3 3 10 3 4 2 4 4 2 4 3 2 2
     
    Sample Output
     
    2 7
     

    题意:

      给你一个数组,每个值代表一种颜色,每次选一个区间涂颜色,代价是区间内颜色种类数的平方,涂完所有数组,问你最小代价是多少

    题解:

      设定dp[i]为前i个数的最小代价,

      那么转移就是dp[i] = min{dp[j]+cal(j+1,i)^2} cal计算区间内颜色种类数

      明显超时;

      当你从i-1遍历到0去寻找那个最小dp[j]+cal(j+1,i)^2时,有些电视可以跳跃的,那就是在k~i-1里面出现过的,就可以跳过,这个用双向链表实现

      还有一个优化:当向前遍历时,不同个数的平方已经超过单独涂色的值 即 cal(j+1,i)^2>i 直接跳出

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<map>
    using namespace std;
    const int N = 1e5+10, M = 2e2+11, inf = 2e9, mod = 1e9+7;
    int dp[N],a[N],pre[N],nex[N],n;
    map<int,int >mp;
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            mp.clear();
            memset(dp,127,sizeof(dp));
            for(int i=1;i<=n;i++)scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)nex[i]=i+1,pre[i]=i-1;
            dp[0]=0,pre[0]=-1;
            for(int i=1;i<=n;i++)
            {
                if(!mp[a[i]]) mp[a[i]]=i;
                else
                {
                    int id = mp[a[i]];
                    nex[pre[id]] = nex[id];
                    pre[nex[id]] = pre[id];
                    mp[a[id]] = i;
                }
                int num = 0;
                for(int j=pre[i];j!=-1;j=pre[j])
                {
                    num++;
                    dp[i] = min(dp[i],dp[j]+num*num);
                    if(num*num>i) break;
                }
            }
            printf("%d
    ",dp[n]);
        }
        return 0;
    }
  • 相关阅读:
    华硕ASUS A3V 拆解图 http://m.linktone.com/report/pdjj/14001781862.shtml
    华硕A3V 迅驰 配置详情
    Dvbbs 更换论坛置顶图片
    Flash 图片轮换效果
    动网官方最新dvbbs7.1sp1商业版下载,附存储过程解密代码!
    在VC中为应用程序添加图形超链接功能
    VC常见数据类型转换详解
    查询Access逻辑字段遇到的问题 武胜
    几个不错的开源的.net界面控件 转自http://zchuang2004.spaces.live.com/blog/cns!8C4AEEE059DED8B1!157.entry 武胜
    C#正则表达式整理备忘 转载(http://www.cnblogs.com/KissKnife/archive/2008/03/23/1118423.html) 武胜
  • 原文地址:https://www.cnblogs.com/zxhl/p/5657345.html
Copyright © 2020-2023  润新知