zoukankan      html  css  js  c++  java
  • 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, 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
     
    Source
     
    题意:一个数列,每个点代表一种颜色,每次选一个区间覆盖,覆盖的代价是区间内颜色种类数的平方,直到覆盖整个数列,求最小花费
    
    思路:1、首先将相邻的两个相同的数合并,记录下它的idd号和数值
    
         2、然后要将的值离散化,因为后面要用到标记数组vis,而a[i]的范围太大(10e9),所以要离散化后才能标记
    
         3、定义一个dp[]数组,dp[i]表示取到i个数时的最小代价,注意dp[tot]=tot,因为最多也就tot,(可以一个一个取)。
    
         4、这边有个剪枝(至关重要,不剪枝会超时),即if(dp[i]+tmp*tmp>=dp[tot]) break;
    
         5、 还有两个for应该这样写 for(int i=0;i<tot;i++)
    
                                  for(int j=i+1;j<=tot;j++)
    
             一开始写成O(n^3)了,感觉自己还是太弱了啊。。。。。。。
    
             还有就是第一个for要从0开始,自己写的时候从1开始,导致WA了,各种原因自己慢慢体会
    
         6、还有用到vector容器来清除标记vis,也起到优化时间的作用
     
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<stack>
      5 #include<vector>
      6 #include<set>
      7 #include<algorithm>
      8 using namespace std;
      9 #define inf 1<<26
     10 #define N 60000
     11 int n;
     12 int a[N];
     13 int dp[N];
     14 int vis[N];
     15 set<int> s;
     16 struct Node
     17 {
     18     int idd;
     19     int num;
     20     int rankk;
     21 }p[N];
     22 bool cmp1(Node a,Node b)
     23 {
     24     return a.num<b.num;
     25 }
     26 bool cmp2(Node a,Node b)
     27 {
     28     return a.idd<b.idd;
     29 }
     30 int main()
     31 {
     32     while(scanf("%d",&n)==1)
     33     {
     34         for(int i=1;i<=n;i++)
     35             scanf("%d",&a[i]);
     36 
     37         //int m=n;
     38         int tot=1;
     39         p[tot].idd=tot;
     40         p[tot++].num=a[1];
     41         for(int i=2;i<=n;i++)
     42         {
     43             if(a[i]==a[i-1])
     44                 continue;
     45             else
     46             {
     47                 p[tot].idd=tot;
     48                 p[tot++].num=a[i];
     49             }
     50         }
     51         //for(int i=1;i<tot;i++)
     52            // printf("---%d %d
    ",p[i].idd,p[i].num);
     53 
     54         tot--;
     55 
     56         sort(p+1,p+1+tot,cmp1);
     57 
     58         p[1].rankk=1;
     59         int w=2;
     60         for(int i=2;i<=tot;i++)
     61         {
     62             if(p[i].num!=p[i-1].num)
     63             {
     64                 p[i].rankk=w;
     65                 w++;
     66             }
     67             else
     68             {
     69                 p[i].rankk=p[i-1].rankk;
     70             }
     71         }
     72 
     73         sort(p+1,p+1+tot,cmp2);
     74         for(int i=1;i<=tot;i++)
     75             dp[i]=inf;
     76 
     77         vector<int>v;
     78         dp[0]=0;
     79         dp[tot]=tot;
     80         for(int i=0;i<tot;i++)
     81         {
     82             int tmp=0;
     83             for(int j=i+1;j<=tot;j++)
     84             {
     85                 if(!vis[p[j].rankk])
     86                 {
     87                     v.push_back(p[j].rankk);
     88                     vis[p[j].rankk]=1;
     89                     tmp++;
     90                 }
     91                 if(dp[i]+tmp*tmp>=dp[tot]) break;
     92                 dp[j]=min(dp[j],dp[i]+tmp*tmp);
     93             }
     94             for(int i=0;i<v.size();i++)
     95                 vis[v[i]]=0;
     96             v.clear();
     97         }
     98         printf("%d
    ",dp[tot]);
     99     }
    100     return 0;
    101 }
    View Code
     
  • 相关阅读:
    博客作业,每周例行报告 第二次作业
    接口基本知识
    python学习-unittest笔记
    读取monkey日志,并存放到另一个文件中
    python学习1-django创建项目及应用
    简单正则表达式python
    adb devices 显示端口被占用时如何处理
    将txt文件 导入到excel中
    将 列表转换成 字典格式
    将文件中的内容读出来且 用逗号隔开换行显示
  • 原文地址:https://www.cnblogs.com/UniqueColor/p/4738126.html
Copyright © 2011-2022 走看看