您的位置:首页 > 大数据 > 人工智能

hdu5009 Paint Pearls(离散+线性dp)

2015-08-24 11:33 501 查看
题目链接:点击打开链接

题意描述:现有一串珍珠(直线)对珍珠进行染色,给定目标颜色,每次染色可以染一段连续的区间,消耗的代价为连续区间内颜色的种类数的平方,问代价最小多少?

此题数据估计比较弱吧,O(n^2)的时间复杂度竟然能过,n可是5w呀

解题思路:dp

预处理:首先对连续的相同颜色进行压缩(如果连续且颜色相同则相当于一个),然后对颜色进行离散化(便于标记)

dp处理:dp[i]表示以第i个珍珠结尾的最小代价,状态转移方程dp[j]=min(dp[j],dp[i]+cnt*cnt);///cnt代表从i到j的区间内颜色的种类数

关键剪枝:当dp[i]+cnt*cnt>n时跳出内层循环

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define INF 1e9+7
using namespace std;
const int MAXN=50005;
int n,vis[MAXN];
int dp[MAXN];
vector<int> save;
struct node{
int val,id,rank;
}p[MAXN];
bool cmp1(node a,node b){
return a.val<b.val;
}
bool cmp2(node a,node b){
return a.id<b.id;
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;++i) scanf("%d",&p[i].val);
int pn=1;
for(int i=2;i<=n;++i)
if(p[i].val!=p[i-1].val) p[++pn]=p[i];
n=pn;
for(int i=1;i<=n;i++)
p[i].id=i;
sort(p+1,p+n+1,cmp1);
p[1].rank=0;
int s=0;
for(int i=2;i<=n;++i){
if(p[i].val!=p[i-1].val) ++s;
p[i].rank=s;
}
sort(p+1,p+n+1,cmp2);
memset(dp,INF,sizeof(dp));
dp[0]=0;
dp
=n;///最大为n,限定上界

for(int i=0;i<n;++i){
int cnt=0;
for(int j=i+1;j<=n;++j){
if(vis[p[j].rank]==0){
save.push_back(p[j].rank);
cnt++;
}
vis[p[j].rank]++;
if(dp[i]+cnt*cnt>=dp
) break;///关键剪枝
dp[j]=min(dp[j],dp[i]+cnt*cnt);
}
int len=save.size();///vector用于加速
for(int i=0;i<len;++i)
vis[save[i]]=0;
save.clear();
}
printf("%d\n",dp
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: