zoukankan      html  css  js  c++  java
  • [HDU 5009]Paint Pearls(DP)

    [HDU 5009]Paint Pearls(DP)

    题面

    一个序列,每个值代表一种颜色,每次选一个区间覆盖,覆盖的代价是区间内颜色种类数的平方,直到覆盖整个数列,求最小花费

    分析

    (dp[i])表示覆盖前(i)位的最小花费,那么显然有

    [dp[i]=min_{j=0}^{i-1}(dp[j]+num(j+1,i)^2) ]

    其中(num(l,r))表示区间([l,r])内的颜色种类数。

    直接求解显然是(O(n^2))的,而这个式子看起来也很难优化。考虑剪枝。

    首先(dp[i] leq i), 因为如果每个点单独覆盖,每次覆盖的代价是1,总代价为i

    还有一个强力的剪枝是重复的数只用保留最后一个,其他重复的可以删去。考虑到j从i-1倒序枚举到1时,若出现重复的a[j],加入之后不会使num变大.如果j是最后一个,那么前面的数的代价已经在计算dp[j]的时候算过了.因此不会影响结果

    这样就可以保证转移时每个权值只出现一次.又因为权值总数的平方超过(i)时就可以停止转移。总时间复杂度为(O(nsqrt n)).删除操作可以用双向链表实现

    代码

    //http://119.29.55.79/problem/1502
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define maxn 100000
    using namespace std;
    int n;
    int a[maxn+5];
    void discrete(int *a,int n) {
    	static int b[maxn+5];
    	for(int i=1; i<=n; i++) b[i]=a[i];
    	sort(b+1,b+1+n);
    	int sz=unique(b+1,b+1+n)-b-1;
    	for(int i=1; i<=n; i++) a[i]=lower_bound(b+1,b+1+sz,a[i])-b;
    
    }
    
    struct list {
    	int pre[maxn+5],nex[maxn+5];
    	void ini(int n) {
    		pre[0]=-1;//相当于NULL
    		for(int i=1; i<=n; i++) {
    			pre[i]=i-1;
    			nex[i]=i+1;
    		}
    	}
    	void del(int x) {
    		nex[pre[x]]=nex[x];
    		pre[nex[x]]=pre[x];
    	}
    } L;
    int lst[maxn+5];
    int dp[maxn+5];
    void ini(){
    	memset(lst,0,sizeof(lst));
    	memset(dp,0,sizeof(dp));
    }
    int main() {
    	while(scanf("%d",&n)!=EOF) {
    		ini(); 
    		for(int i=1; i<=n; i++) scanf("%d",&a[i]);
    		discrete(a,n);
    		L.ini(n);
    		dp[0]=0;
    		for(int i=1; i<=n; i++) dp[i]=i; //每个数一段,答案最大不超过i
    		for(int i=1; i<=n; i++) {
    			if(lst[a[i]]) L.del(lst[a[i]]);	//相同的数只保留最后一个
    			//考虑到j从i-1倒序枚举到1时,若出现重复的a[i],除第一次出现外应该删去,
    			//因为枚举到的a[i]加入num^2部分不会使num变大,所以dp[i]和它前后的dp值应该是等价的
    			lst[a[i]]=i;
    			int num=0;
    			for(int j=L.pre[i]; j!=-1; j=L.pre[j]) {
    				num++;
    				if(num*num>i) break;//如果超过i显然不优,可以直接break掉
    				dp[i]=min(dp[i],dp[j]+num*num);
    			}
    		}
    		printf("%d
    ",dp[n]);
    	}
    }
    
    
  • 相关阅读:
    Mvc+三层(批量添加、删除、修改)
    js中判断复选款是否选中
    EF的优缺点
    Git tricks: Unstaging files
    Using Git Submodules
    English Learning
    wix xslt for adding node
    The breakpoint will not currently be hit. No symbols have been loaded for this document."
    Use XSLT in wix
    mfc110ud.dll not found
  • 原文地址:https://www.cnblogs.com/birchtree/p/12266123.html
Copyright © 2011-2022 走看看