hdu 5009 Paint Pearls(dp)

来源:互联网 发布:mac 10 少女前线 编辑:程序博客网 时间:2024/05/22 07:45

题意:有n个珠子,每个珠子有一个想要被涂成的颜色,每次可以选择一个区间进行涂色,花费为区间中不同颜色的珠子的数量的平方,求最小的花费将所有的珠子涂成目标颜色。

思路:可以假定涂色是从左到右一段一段涂的,不会选择相交的区间(不会得到任何好处)。那么用dp[i]表示涂完1~i的最小花费,dp[i] = min(dp[j] + differentcolor[j+1][i]^2),其中j < i。但是这样写复杂度很高,发现要增加的花费,即differentcolor[j+1][i] <= totalcolor^2,即最差也可以将n个珠子直接合并。那么其实这个状态只要向前找sqrt(n)个就行了。从左到右扫一遍,维护从位置j到当前位置i有k个不同的颜色的最小dp值的位置minp[i]。若lastp[c]表示上一个颜色c出现的位置,那么对于当前位置i,lastp[color[i]] + 1 ~ i的所有位置的不同颜色数都要加1,扫一遍minp,我们就知道哪些minp[c]要变成minp[c+1]了。吐槽一下数据,真是太水啦~


代码:


#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn = 50000 + 10;ll dp[maxn];int color[maxn],minp[255];int lastp[maxn];map<int,int>mp;int main(){//    freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n;    while(~scanf("%d",&n))    {        mp.clear();        int cnt = 0;        for(int i = 1;i <= n;++i)        {            scanf("%d",&color[i]);            if(mp.find(color[i]) == mp.end())            {                mp[color[i]] = ++cnt;                color[i] = cnt;            }            else                color[i] = mp[color[i]];        }        int m = min(cnt,(int)sqrt(n) + 1);        memset(lastp,0,sizeof(lastp));        memset(minp,0,sizeof(minp));        dp[0] = 0;        for(int i = 1;i <= n;++i)        {            dp[i] = dp[i-1] + 1;            for(int j = m;j >= 1;--j)            {                if(minp[j] > lastp[color[i]])                    minp[j] = 0;                if(minp[j-1] && minp[j-1] > lastp[color[i]])                {                    if(minp[j] == 0)                        minp[j] = minp[j-1];                    else if(dp[minp[j]-1] > dp[minp[j-1]-1])                        minp[j] = minp[j-1];                }                if(minp[j])                    dp[i] = min(dp[i],dp[minp[j]-1] + (ll)j*j);            }            if(!minp[1])                minp[1] = i;            else if(dp[i-1] <= dp[minp[1]-1])                minp[1] = i;            lastp[color[i]] = i;        }        printf("%I64d\n",dp[n]);    }    return 0;}


0 0
原创粉丝点击