ickchen2

zoj 3399 Classes Division

这题很明显的是DP,DP方程很容易就想到为dp[i,j]=min(dp[k][j-1]+(sum[i]-sum[k])*g[j])(n-b<=k<n-a)
但普通转移必定挂。
如果把方程变一变dp[i,j]=sum[i]*g[j]+min(dp[k][j-1]-sum[k]*g[j])
这样在如果j不变的情况下,后面的最小值是不变的。因此可以O(1)的转移
但由于存在范围,因此可以利用堆或者单调队列来处理

  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<string>
  4 #include<vector>
  5 #include<map>
  6 #include<queue>
  7 #include<algorithm>
  8 #define M 1000
  9 #define clr(x) memset(x,0,sizeof(x))
 10 #define _clr(x) memset(x,-1,sizeof(x))
 11 #define fr(i,a,b) for( i=a;i<b;++i)
 12 #define pf printf
 13 #define sf scanf
 14 #define pb push_back
 15 #define mp make_pair
 16 #define ll long long
 17 #define debug 1
 18 using namespace std;
 19 const ll oo=100000000000000ll;
 20 ll dp[205][10005];
 21 int x[11000],g[210];
 22 ll sum[11000];
 23 ll L;
 24 int n,k,A,B;
 25 inline
 26 ll sqr(ll x)
 27 {
 28     return (ll)x*x;
 29 }
 30 void init()
 31 {
 32     int i;
 33     L=0;
 34     fr(i,1,n+1)
 35     {
 36         L+=x[i];
 37     }
 38     L=L/n;
 39     sum[0]=0;
 40     fr(i,1,n+1)
 41     {
 42         sum[i]=sum[i-1]+sqr(x[i]-L);
 43     }
 44 }
 45 int l,r;
 46 struct node
 47 {
 48     ll t;
 49     int pos;
 50     node(){}
 51     node(ll t,int pos):t(t),pos(pos){}
 52 };
 53 int operator <(const node &a,const node&b)
 54 {
 55     return a.t<b.t||a.t==b.t&&a.pos<b.pos;
 56 }
 57 const int queuesize=10005;
 58 node q[queuesize];
 59 inline
 60 ll min(ll a,ll b)
 61 {
 62     return a<b?a:b;
 63 }
 64 void sol()
 65 {
 66     int i,j;
 67     fr(i,0,k+1)
 68     {
 69         fr(j,0,n+1)
 70             dp[i][j]=oo;
 71     }
 72     dp[0][0]=0;
 73     ll ans=-1;
 74     int cl=k+1,T=n+1;
 75     fr(i,1,k+1)
 76     {
 77         l=0,r=0;
 78         fr(j,A,n+1)
 79         {
 80             if(dp[i-1][j-A]!=oo)
 81             {
 82                 node tem=node(dp[i-1][j-A]-sum[j-A]*g[i],j-A);
 83                 while(l<r&&q[r-1].t>=tem.t)--r;
 84                 q[r++]=tem;
 85             }
 86 
 87             while(l<r&&q[l].pos<j-B)++l;
 88             if(l==r)continue;
 89             dp[i][j]=q[l].t+sum[j]*g[i];
 90         }
 91         if(dp[i][n]!=oo)
 92         {
 93             if(ans==-1||ans>dp[i][n])
 94             {
 95                 ans=dp[i][n];
 96                 cl=i;
 97                 T=n-q[l].pos;
 98             }
 99         }
100     }
101     if(ans!=-1)
102         pf("%lld %d %d\n",ans,cl,T);
103     else
104         pf("No solution.\n");
105 }
106 int main()
107 {
108     freopen("in.txt","r",stdin);
109     int i;
110     int ca=0;
111     while(sf("%d%d%d%d",&n,&k,&A,&B)>0)
112     {
113         //if(ca++)pf("\n");
114         fr(i,1,n+1)
115         {
116             sf("%d",&x[i]);
117         }
118         fr(i,1,k+1)
119         {
120             sf("%d",&g[i]);
121         }
122         init();
123         sol();
124     }
125     return 0;
126 }
127 

posted on 2010-09-07 22:08 神之子 阅读(197) 评论(0)  编辑 收藏 引用 所属分类: zoj月赛


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿(1)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜