HDU 5009

http://acm.hdu.edu.cn/showproblem.php?pid=5009

题意:一个数列,每个点代表一种颜色,每次选一个区间覆盖,覆盖的代价是区间内颜色种类数的平方,直到覆盖整个数列,求最小花费

思路:首先合并颜色相同的点,接着离散化颜色,做dp,dp[i]表示取到位置i的最小花费,注意到答案最大值应该是合并后的数列长度,这是一个剪枝,为了避免每次循环memset vis数组,要把每次访问的颜色值记录在一个vector中,然后只清vector内的颜色清空vector 即可

这道题总的来说出的感觉比较怪,时间卡的很死,复杂度也怪怪的(具体复杂度不会算,但觉得如此dp应该tle才对),还要用一些非常奇怪的小技巧(加vector数组)。题不难,但是网赛时能当场AC的人真的是胆大又自信。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std ;

const int INF=0xfffffff ;

int n,dp[50005] ;

struct node
{
    int num ;
    int id,rank ;
}kk[50005] ;
int a[50005] ;
int vis[50005] ;
int cmp1(node aa,node bb)
{
    return aa.num<bb.num ;
}
int cmp2(node aa,node bb)
{
    return aa.id<bb.id ;
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1 ;i<=n ;i++)
        {
            scanf("%d",&a[i]) ;
        }
        int m=n ;
        for(int i=2 ;i<=n ;i++)
        {
            if(a[i]==a[i-1])
            {
                m-- ;
            }
        }
        int cnt=2 ;
        kk[1].id=1 ;kk[1].num=a[1] ;
        for(int i=2 ;i<=n ;i++)
        {
            if(a[i]!=a[i-1])
            {
                kk[cnt].id=cnt ;
                kk[cnt].num=a[i] ;
                cnt++ ;
            }
        }
        /*
        for(int i=1 ;i<=m ;i++)
        {
            printf("%d %d ",kk[i].num,kk[i].id) ;
        }
        printf("\n") ;
        */
        sort(kk+1,kk+1+m,cmp1) ;
        kk[1].rank=1 ;
        cnt=2 ;
        for(int i=2 ;i<=m ;i++)
        {
            if(kk[i].num!=kk[i-1].num)
            {
                kk[i].rank=cnt++ ;
            }
            else kk[i].rank=kk[i-1].rank ;
        }
        sort(kk+1,kk+1+m,cmp2) ;
        /*
        for(int i=1 ;i<=m ;i++)
        {
            printf("%d ",kk[i].rank) ;
        }
        printf("\n") ;
        */
        for(int i=0 ;i<50005 ;i++)
            dp[i]=INF ;
        dp[0]=0 ;
        dp[m]=m ;
        vector <int> v ;
        for(int i=0 ;i<m ;i++)
        {
            cnt=0 ;
            for(int j=i+1 ;j<=m ;j++)
            {
                if(!vis[kk[j].rank])
                {
                    v.push_back(kk[j].rank) ;
                    vis[kk[j].rank]=1 ;
                    cnt++ ;
                }
                if(dp[i]+cnt*cnt>=dp[m])break ;
                dp[j]=min(dp[j],dp[i]+cnt*cnt) ;
            }
            //memset(vis,0,sizeof(vis)) ;
            for(int j=0 ;j<v.size() ;j++)
                vis[v[j]]=0 ;
            v.clear() ;
        }
        printf("%d\n",dp[m]) ;
    }
    return 0 ;
}

时间: 2024-10-13 08:03:14

HDU 5009的相关文章

HDU 5009 Paint Pearls _(:зゝ∠)_2014 ACM/ICPC Asia Regional Xi&#39;an Online

呵呵 #include <cstdio> #include <algorithm> #include <iostream> #include <cstring> typedef long long ll; using namespace std; const int N = 5 * 10000 + 5; int xval[N], dep; int n, a[N], pre[N]; ll d[N]; int pos[300], dd; void work()

HDU 5009 Paint Pearls(西安网络赛C题)

HDU 5009 Paint Pearls 题目链接 题意:给定一个目标颜色,每次能选一个区间染色,染色的代价为这个区间不同颜色数的平方,问最小代价 思路:先预处理,把相同颜色的一段合并成一个点,然后把颜色离散化掉,然后进行dp,dp[i]表示染到第i个位置的代价,然后往后转移,转移的过程记录下不同个数,这样就可以转移了,注意加个剪枝,就是如果答案大于了dp[n]就不用往后继续转移了 代码: #include <cstdio> #include <cstring> #include

HDU 5009 Paint Pearls(西安网络赛C题) dp+离散化+优化

转自:http://blog.csdn.net/accelerator_/article/details/39271751 吐血ac... 11668627 2014-09-16 22:15:24 Accepted 5009 1265MS 1980K 2290 B G++ czy   Paint Pearls Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Subm

HDU - 5009 Paint Pearls(dp+双向链表优化)

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,

hdu 5009 Paint Pearls (dp)

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,

hdu 5009 Paint Pearls

首先把具有相同颜色的点缩成一个点,即数据离散化. 然后使用dp[i]表示涂满前i个点的最小代价.对于第i+1个点,有两种情况: 1)自己单独涂,即dp[i+1] = dp[i] + 1 2)从第k个节点之后(不包括k)到第i+1个节点一次涂完,且一起涂的节点共有num种颜色,即dp[i+1] = dp[k] + num * num 从而可以得到状态转移方程dp[i+1] = min(dp[i], dp[k] + num * num) 但是如果从后往前遍历每一个k,会超时. 因此我们可以使用双向链

HDU 5009 Paint Pearls (动态规划)

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 eac

HDU 5009 (dp+双向链表优化)

西安网络预赛题. 连续选区间填充,完全覆盖. dp[i] 完全覆盖的最优解. 连续一起的同种颜色缩并. 优化: 1. 至多每个单独选,价值最高为N 2.不能连续选择超过sqrt(N)+1个不同的颜色 3.第i种颜色来的时候,它之前本身的颜色不再考虑. PS:此题本来打算离散化数据,但是用map就不用了(直接判重).对于有序的数据,离散化还要再映射 #include <iostream> #include <cmath> #include <cstdio> #includ

AC日记——Paint Pearls hdu 5009

Paint Pearls 思路: 离散化+dp+剪枝: dp是个n方的做法: 重要就在剪枝: 如果一个长度为n的区间,有大于根号n种颜色,还不如一个一个涂: 来,上代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 50005 int n,ai[maxn],dp[maxn],ls[