HDU 5009 Paint Pearls

今天西安网赛的题,因为被那个博弈卡住,没什么心情看这个

这个题好像很简单的样子,但是看了下数据量,发现用n^2承受不起,然后我想了一下 没想出什么更低复杂度的算法出来。。

后来发现别人还是用n方算法过的,只是用了下剪枝。。。。擦,我不是很敢尝试这种,,估计今天这个简单DP过的人不是很多 就是卡在时间上的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 5*10010;
int A[N],n;
int t[N],ranks[N];
int dp[N];
int vis[N];
vector<int> v;
int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        for (int i=1;i<=n;i++){
            scanf("%d",&A[i]);
            t[i]=A[i];
            dp[i]=1<<30;
            vis[i]=0;
        }
        sort(t+1,t+1+n);
        int m=1,k=1;
        ranks[0]=0;
        for (int i=2;i<=n;i++){
            if (t[i]!=t[i-1]){
                t[++m]=t[i];
            }
            if (A[i]!=A[i-1]){
                A[++k]=A[i];
                ranks[k-1]=i-k+1;
            }
        }
        ranks[k]=n-k+1;
        for (int i=1;i<=k;i++){
            int pos=lower_bound(t+1,t+1+m,A[i])-t;
            A[i]=pos;
        }
        dp[0]=0;
        dp[k]=k;
        for (int i=0;i<k;i++){
            int cnt=0;
            if (dp[i]>=dp[i+1]) continue;
            for (int j=i+1;j<=k;j++){
                if (!vis[A[j]]){
                    cnt++;
                    v.push_back(A[j]);
                }
                vis[A[j]]++;
                if (dp[i]+cnt*cnt>=dp[k]) break;
                dp[j]=min(dp[j],dp[i]+cnt*cnt);
            }
            for (int j=0;j<v.size();j++){
                vis[v[j]]=0;
            }
            v.clear();
        }
        printf("%d\n",dp[k]);

    }
}

  

posted @ 2014-09-14 21:22  KRisen  阅读(730)  评论(2编辑  收藏  举报