首页 > 代码库 > AC日记——Paint Pearls hdu 5009

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 50005int n,ai[maxn],dp[maxn],ls[maxn],size,num,map[maxn];inline void in(int &now){    char Cget=getchar();now=0;    while(Cget>9||Cget<0) Cget=getchar();    while(Cget>=0&&Cget<=9)    {        now=now*10+Cget-0;        Cget=getchar();    }}int main(){    while(scanf("%d",&n)==1)    {        num=0;        for(int i=1;i<=n;i++)        {            in(ai[i]);            if(ai[i]==ai[i-1])            {                n--,i--;                continue;            }            ls[i]=ai[i];        }        sort(ls+1,ls+n+1),size=unique(ls+1,ls+n+1)-ls-1;        for(int i=1;i<=n;i++) ai[i]=lower_bound(ls+1,ls+size+1,ai[i])-ls,map[ai[i]]=0;        for(int i=1;i<=n;i++)        {            if(!map[ai[i]]) num++;            map[ai[i]]++,dp[i]=min(num*num,i);        }        for(int i=1;i<=n;i++) map[ai[i]]--;        for(int i=1;i<=n;i++)        {            if(dp[i]>=dp[i+1]) continue;            num=0;            for(int j=i+1;j<=n;j++)            {                if(!map[ai[j]]) num++;                if(num*num+dp[i]>=dp[n])                {                    for(int v=j-1;v>=i+1;v--) map[ai[v]]--;                    break;                }                map[ai[j]]++,dp[j]=min(dp[j],dp[i]+num*num);            }        }        printf("%d\n",dp[n]);    }    return 0;}

 

AC日记——Paint Pearls hdu 5009