hdu 5009 Paint Pearls(DP+链表优化)
来源:互联网 发布:删除表数据 truncate 编辑:程序博客网 时间:2024/06/07 01:13
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 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
2014 ACM/ICPC Asia Regional Xi’an Online
题意:给定一系列目标颜色,每次能选一个区间染色,染色的代价为这个区间不同颜色数的平方,问最小代价
ps:知道了题意,但是完全没思路啊。。。。
看一下大神的思路:
双向链表优化dp。dp[i]表示涂完前i个所花的最小代价,显然有dp[i]=min{dp[i],dp[j]+num(j+1,i)^2},其中1<=j<i,num(j+1,i)表示区间[j+1,i]的颜色个数。
这样复杂度为O(n^2)显然超时。那么需要优化一下,比如第二组测试数据3 4 2 4 4 2 4 3 2 2,假设dp[1]…dp[8]已更新完毕,现在要更新dp[9],可以看到a[9]为2,按照原始的dp[i]=min{dp[i],dp[j]+num(j+1,i)^2},
i=9,枚举j=8,dp[9]=min{dp[9],dp[8]+1^2};j=7,dp[9]=min{dp[9],dp[7]+2^2};现在貌似没什么变化。。。
j=6,这里就神奇了,如果dp[9]=min{dp[9],dp[6]+3^2},那么这个就太弱了,因为此时2 4 3是连着涂的,但是2之前是3 4 2 4 4,这些如果跟着一起涂,那么仍然是3^2的代价,但前面的数字变少了,显然这种更优。
于是乎dp[9]=min{dp[9],dp[0]+3^2},可以看到6直接跳到了0,为什么这么跳?因为这之前都是些234啊,重复了没必要保存。所以在dp时,我们只需要维护好前后关系即可。
比如当前dp第i位,那么即a[i]加进来,所以之前如果有a[i]值的必须删掉,具体双向链表维护。因此可以看到任意时刻,每种颜色只会保存一次,复杂度就降下来了。
但仍然可以给出坑爹的数据,比如1 2 3 4 … n那么这个dp的话,复杂度仍为O(n^2),于是继续优化。我们知道如果一个一个涂,那么需要花费n。所以最优方案不能大于n,也就是不能连着sqrt(n)个不同的颜色一起涂,否则代价大于n了,这里进行剪枝。复杂度降为O(nsqrt(n)),还是可以接受的。
代码:
#include<stdio.h>#include<map>#include<string.h>using namespace std;#define maxn 50010#define min(a,b) (a<b?a:b)const int inf=0x3f3f3f3f;int pre[maxn],nxt[maxn],a[maxn],dp[maxn];map<int,int>mp;int main(){ int n; while(~scanf("%d",&n)) { mp.clear(); for(int i=1; i<=n; ++i) { scanf("%d",a+i); pre[i]=i-1; nxt[i]=i+1; } memset(dp,inf,sizeof(dp)); dp[0]=0,pre[0]=-1; for(int i=1; i<=n; ++i) { if(!mp.count(a[i]))//这种颜色有没有出现过 mp[a[i]]=i; else//消除重复的颜色 { int tmp=mp[a[i]]; pre[nxt[tmp]]=pre[tmp]; nxt[pre[tmp]]=nxt[tmp]; mp[a[i]]=i; } int cnt=0; for(int j=pre[i];j!=-1;j=pre[j])//更新最优解 { ++cnt; if(cnt*cnt>i) break; dp[i]=min(dp[i],dp[j]+cnt*cnt); } } printf("%d\n",dp[n]); } return 0;}
总结:思路很妙,我想的话只知道要暴力,却想不到该怎样优化,,,
推导一下这种思路的思考过程,先想到用dp,但是n^2要超,然后想到既然和颜色的种类有关,那就让它只有这几种不重复的颜色,所以想到了通过模拟链表来删除相同的颜色。
现在还是不太理解dp的妙用呀,感觉dp真的是最难理解的一部分,要多加努力了!
- hdu 5009 Paint Pearls(DP+链表优化)
- HDU - 5009 Paint Pearls(dp+双向链表优化)
- hdu 5009 Paint Pearls(dp)
- 【HDU】5009 Paint Pearls DP
- hdu 5009 Paint Pearls(dp)
- Hdu 5009 Paint Pearls(dp)
- hdu-5009-Paint Pearls-dp
- Paint Pearls(HDU 5009)
- HDU 5009 Paint Pearls 解题报告(DP)
- hdu 5009 Paint Pearls
- hdu Paint Pearls 5009
- hdu 5009 Paint Pearls
- hdu 5009 Paint Pearls
- hdu 5009 Paint Pearls
- HDU 5009 Paint Pearls
- HDU 5009 Paint Pearls
- HDU 5009 Paint Pearls (动态规划)
- 【DP】 HDOJ 5009 Paint Pearls
- 深度学习各种优化函数详解
- AndroidStudio生成全局变量快捷键
- 利用自动索引计算数组元素的平方和
- 线段树模板
- 递推最小二乘辨识平面双机械臂Matlab代码
- hdu 5009 Paint Pearls(DP+链表优化)
- 列类型
- 父进程是init一定不会变僵尸进程吗?
- 分类(Classification):Probability Generative Model
- JS级联菜单
- CentOS 配置LAMP(Apache+MySQL+PHP)环境,并配置phpmyadmin
- 题目1113:二叉树 九度OJ
- 自定义控件(31)---贝塞尔曲线
- JSP四大作用域和跳转、重定向