首先把具有相同颜色的点缩成一个点,即数据离散化。

然后使用dp[i]表示涂满前i个点的最小代价。对于第i+1个点,有两种情况:

1)自己单独涂,即dp[i+1] = dp[i] + 1

2)从第k个节点之后(不包括k)到第i+1个节点一次涂完,且一起涂的节点共有num种颜色,即dp[i+1] = dp[k] + num * num

从而可以得到状态转移方程dp[i+1] = min(dp[i], dp[k] + num * num)

但是如果从后往前遍历每一个k,会超时。

因此我们可以使用双向链表来把每种颜色最后出现的位置穿起来。对于每一个新加入的点,如果该点颜色没出现过,那么把它加入到双向链表的结尾。如果该点出现过,把它最后出现的位置从双向链表中删除,并把最新的位置加入到双向链表结尾。

需要注意的是要建立一个头节点,使得第一个节点不会因为后面出现了同样的颜色而被删除,从而无法计算从头到尾一次性涂完的情况。

第二个要注意的是如果num * num 已经大于了每个节点单独涂的代价 i,那么就没有必要再往前查找了。

代码如下:

 #define MAXN 50005
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#include <map>
#include <limits.h> using namespace std;
int arr[MAXN];//输入
int l[MAXN];//记录前一个最后出现的颜色的位置
int r[MAXN];//记录后一个最后出现颜色的位置
int dp[MAXN];//dp[i]表示涂到第i个节点最小的代价
int m;//离散化后数组的长度 void solve()
{
map<int, int> exist;//map 存储出当前现过得颜色中,最后出现的位置
int last = ;//双向链表尾
l[] = -;//头节点
r[] = ;//头节点
l[] = ;
exist[arr[]] = ;
dp[] = ;
dp[] = ; for( int i = ; i < m ; i++ )
{
if( exist.count(arr[i]) == )
{
r[last] = i;//添加到尾部
l[i] = last;
last = i;
exist[arr[i]] = i;
}
else
{
int tmp = exist[arr[i]];
r[l[tmp]] = r[tmp];//删除tmp
l[r[tmp]] = l[tmp];//删除tmp
r[last] = i;
l[i] = last;
last = i;
exist[arr[i]] = i;
} int k = last;
dp[i] = dp[i-]+;
int num = ;
while( l[k] >= )
{
dp[i] = min(dp[i], dp[l[k]] + num*num);
num++;
k = l[k];
if( num * num > i )//剪枝
{
break;
}
}
}
printf("%d\n", dp[m-]);
} int main(int argc, char *argv[])
{
int n;
while(scanf("%d", &n) != EOF)
{
int a;
m = ;
for( int i = ; i <= n ; i++ )//从1开始,位置0是头节点
{
scanf("%d", &a);
if( i == )
{
arr[m++] = a;
}
else if( arr[m-] != a )//合并相同颜色的节点,离散化
{
arr[m++] = a;
}
}
solve();
}
return ;
}

hdu 5009 Paint Pearls的更多相关文章

  1. HDU 5009 Paint Pearls(西安网络赛C题) dp+离散化+优化

    转自:http://blog.csdn.net/accelerator_/article/details/39271751 吐血ac... 11668627 2014-09-16 22:15:24 A ...

  2. HDU 5009 Paint Pearls 双向链表优化DP

    Paint Pearls Problem Description   Lee has a string of n pearls. In the beginning, all the pearls ha ...

  3. HDU 5009 Paint Pearls (动态规划)

    Paint Pearls Problem Description Lee has a string of n pearls. In the beginning, all the pearls have ...

  4. HDU - 5009 Paint Pearls(dp+优化双向链表)

    Problem Description Lee has a string of n pearls. In the beginning, all the pearls have no color. He ...

  5. HDOJ 5009 Paint Pearls

    Dicripntion Lee has a string of n pearls. In the beginning, all the pearls have no color. He plans t ...

  6. AC日记——Paint Pearls hdu 5009

    Paint Pearls 思路: 离散化+dp+剪枝: dp是个n方的做法: 重要就在剪枝: 如果一个长度为n的区间,有大于根号n种颜色,还不如一个一个涂: 来,上代码: #include <c ...

  7. hdu5009 Paint Pearls (DP+模拟链表)

    http://acm.hdu.edu.cn/showproblem.php?pid=5009 2014网络赛 西安 比较难的题 Paint Pearls Time Limit: 4000/2000 M ...

  8. Paint Pearls

    Paint Pearls 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5009 dp+双向链表优化 看到题目,很自然地可以定义状态:dp[i]表示涂好 ...

  9. hdu5009 Paint Pearls[指针优化dp]

    Paint Pearls Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

随机推荐

  1. Java获得UTC时间

    在Java语言中,您可以通过java.util.Calendar类取得一个本地时间或者指定时区的时间实例,如下: 取得本地时间: java.util.Calendar cal = java.util. ...

  2. ZOJ 3822 Domination 期望dp

    Domination Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/showProblem ...

  3. Struts2 Action的访问路径

    1.     Action的访问路径 扩展名 缺省以.action结尾,请参考:default.properties文件,可以通过配置改变这一点: <constant name="st ...

  4. css Hack,用IE11模拟测试的,条件注释要找真IE去测,模拟的无效

    <!DOCTYPE html> <!--[if lt IE 7 ]> <html class="ie6 ie"> <![endif]--& ...

  5. 文件和目录之link、unlink、remove和rename函数

    任何一个文件可以有多个目录项指向其i节点.创建一个指向现有文件的链接的方法是使用link函数. #include <unistd.h> int link( const char *exis ...

  6. Android模拟器avd的创建、使用和调试相关命令

    1.创建AVD命令:android-sdk-windows\tools目录下面有android命令  android list 列出当前系统中已安装的Android版本以及已安装的AVD(Androi ...

  7. Config

    Config Config App Auth Cache Database Languages Mail Modules Routing Session Config Settings for the ...

  8. 第一个js程序

    <html><head> <title>Untitled</title> <script >function demo(){ alert ( ...

  9. Spring 事务模型

    一.三种事务模型 1.本地事务模型:开发人员不用知道事务的存在,事务全部交给数据库来管理,数据库自己决定什么时候提交或回滚,所以数据库是事务的管理者. Connection conn=jdbcDao. ...

  10. List的add方法与addAll方法的区别

    add是将传入的参数作为当前List中的一个Item存储,即使你传入一个List也只会另当前的List增加1个元素addAll是传入一个List,将此List中的所有元素加入到当前List中,也就是当 ...