首先把具有相同颜色的点缩成一个点,即数据离散化。
然后使用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,那么就没有必要再往前查找了。
代码如下:
1 #define MAXN 50005 2 #include 3 #include 4 #include 5 #include