zoukankan      html  css  js  c++  java
  • 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("
    ") ;
            */
            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("
    ") ;
            */
            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
    ",dp[m]) ;
        }
        return 0 ;
    }
    View Code
  • 相关阅读:
    拉钩爬取部分重写
    树莓派yolov3 测试训练结果时出现段错误或总线错误解决方法
    服务注册与发现【Eureka】- Eureka自我保护
    服务注册与发现【Eureka】- 服务发现Discovery
    服务注册与发现【Eureka】- 集群Eureka构建步骤
    服务注册与发现【Eureka】- 单机Eureka构建步骤
    服务注册与发现【Eureka】- Eureka简介
    SpringCloud正式开发前 -- 基础项目框架搭建
    服务注册与发现【Zookeeper】
    【校招】【内推】【阿里云】 ECS、神龙计算平台招聘|【经验分享】
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/4005322.html
Copyright © 2011-2022 走看看