HDU
来源:互联网 发布:北京淘宝美工培训2ds 编辑:程序博客网 时间:2024/05/17 04:46
传送门:HDU 5009
题意:给出n个连续的珠子,珠子有不同的颜色,现将其划分成任意多段,每一段的代价为该段中颜色种数的平方,问划分的最小总代价和是多少。
总思路:dp[i]代表处理到第i个珠子的最小花费,显然dp[i] = min(dp[j] + num[i][j] * num[i][j])(0 < j <= i) num[i][j]代表[j...i]区间内的颜色种数。n^2转移显然不能接受。
优化方法1:用双向链表维护珠子的颜色,使得任意时刻已经遍历过的珠子中每种颜色都只保存一个最新位置,每次遇到一个重复的颜色,就将该颜色前一个位置从链表中删除,然后利用双向链表维护dp数组,因为链表每个节点都代表该位置有一个新的颜色,因此可以避免很多无用操作,但这还不够,如果给出序列为1,2,3。。。。n,那么链表就毫无用处了,因此我们还要加一个下界优化:显然dp[n] <= n,因为最差情况每个珠子分一段,这时dp[n] == n。
代码:
#include<bits/stdc++.h>#define ll long long#define pi acos(-1)#define MAXN 50010#define inf 0x3f3f3f3fusing namespace std;typedef pair<int,int>P;int a[MAXN], val[MAXN];int pre[MAXN], nxt[MAXN];int last[MAXN], dp[MAXN]; int main(){int n, m, id, cnt;while(cin >> n){for(int i = 1; i <= n; i++){scanf("%d", a + i);val[i] = a[i];pre[i] = i - 1;nxt[i] = i + 1;last[i] = 0;dp[i] = inf;}dp[0] = 0; pre[0] = -1;sort(val + 1, val + n + 1);m = unique(val + 1, val + n + 1) - val;for(int i = 1; i <= n; i++){a[i] = lower_bound(val + 1, val + m, a[i]) - val;id = last[a[i]];if(id){pre[nxt[id]] = pre[id];nxt[pre[id]] = nxt[id];}last[a[i]] = i;cnt = 0;for(int j = pre[i]; ~j; j = pre[j]){cnt++;dp[i] = min(dp[i], dp[j] + cnt * cnt);if(cnt * cnt >= n) break;}}printf("%d\n", dp[n]);} return 0;}
优化方法2:将连续的同样颜色的珠子缩成一个珠子(易证这样做不影响dp结果的正确性),然后再用下界进行剪枝就行了。代码详见:点击打开链接
阅读全文
0 0
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Hdu
- hdu
- hdu-
- hdu
- hdu
- hdu
- HDU
- _OBJC_CLASS_$_某文件名", referenced from:的问题
- form提交的错觉
- Java动态代理
- mysql用户与权限
- Unity 滑动事件6个方向的实现
- HDU
- CentOS7学习(1)
- [POJ2151]check the difficulty-概率DP
- 算法(二)
- 斯坦福大学CS231课程笔记1
- 安卓逆向环境搭建,SDK manager闪退问题
- Python发展迅速的原因分析
- php JSON数据格式化方法
- ►奇说总002期:《战争中隐秘的智慧较量》10.12