BSOJ 3425:分班 DP+单调队列
2016-11-08 09:49
260 查看
3425 – 【模拟试题】分班
Description
Input
本题目有多组数据。第一行有一个整数case(<=10),表示有case组数据。
接下来对于每组数据的第一行有4个正整数,依次是M,N,A,B。
第二行有M个正整数,用空格隔开,分别是X[1],X[2] —–X[M]。
第三行有N个正整数,用空格隔开,分别是G[1],G[2] —–G
。
Output
对于每组数据,要输出三个正整数,以空格隔开,不同数据之间要换行。
三个正整数分别为sigma,class,last。分别表示最小的评价指数。在评价指数最小的情况下,安排的教室的最小数目。在评价指数,安排教师数目最小的情况下,最后一个教室的人数的最小数目。
Sample Input
1
10 3 1 4
16 11 12 13 10 15 16 17 18 14
4 5 1
Sample Output
186 3 4
Hint
【样例解释】
前4个,后4个,中间2个。
求的是sigma((xi-ave)^2)*G[g[i]],ave和xi都是常数,也就将问题简化为一个分配问题。
设f[i][j]为前i个学生,分j班,且当前为第j班的最小评价分数,容易写出DP方程:
f[i][j]=min{f[k][j-1]+G[j]*(sumx[i]-sumx[k])};
(i-B<=k<=i-A)
这是一个O(mn^2)的递推式,只拿得到40分。
考虑优化,使用单调队列,更新f[i][j]的时候一步得到f[k][j-1]-G[j]*sumx[k]的最小值,注意这里用单调队列不仅仅维护f[k][j-1],因为后面还有一项与k有关,故要全部带进去,否则是错误的,对于第2、3问,根据贪心(误?),更小解出现时即更新其答案即可。至此问题得解。
hint:
1. 这里的单调队列只与j-1的各项有关,也即每次j变化,要把头尾指针清零。
2. 递推的方向为上一个班->当前班(j-1->j),可以使用滚动数组,并且DP第一位一定为j。
滚动数组太丑了..考试的时候作死写一个然后惨遭爆零..
Description
Input
本题目有多组数据。第一行有一个整数case(<=10),表示有case组数据。
接下来对于每组数据的第一行有4个正整数,依次是M,N,A,B。
第二行有M个正整数,用空格隔开,分别是X[1],X[2] —–X[M]。
第三行有N个正整数,用空格隔开,分别是G[1],G[2] —–G
。
Output
对于每组数据,要输出三个正整数,以空格隔开,不同数据之间要换行。
三个正整数分别为sigma,class,last。分别表示最小的评价指数。在评价指数最小的情况下,安排的教室的最小数目。在评价指数,安排教师数目最小的情况下,最后一个教室的人数的最小数目。
Sample Input
1
10 3 1 4
16 11 12 13 10 15 16 17 18 14
4 5 1
Sample Output
186 3 4
Hint
【样例解释】
前4个,后4个,中间2个。
求的是sigma((xi-ave)^2)*G[g[i]],ave和xi都是常数,也就将问题简化为一个分配问题。
设f[i][j]为前i个学生,分j班,且当前为第j班的最小评价分数,容易写出DP方程:
f[i][j]=min{f[k][j-1]+G[j]*(sumx[i]-sumx[k])};
(i-B<=k<=i-A)
这是一个O(mn^2)的递推式,只拿得到40分。
考虑优化,使用单调队列,更新f[i][j]的时候一步得到f[k][j-1]-G[j]*sumx[k]的最小值,注意这里用单调队列不仅仅维护f[k][j-1],因为后面还有一项与k有关,故要全部带进去,否则是错误的,对于第2、3问,根据贪心(误?),更小解出现时即更新其答案即可。至此问题得解。
hint:
1. 这里的单调队列只与j-1的各项有关,也即每次j变化,要把头尾指针清零。
2. 递推的方向为上一个班->当前班(j-1->j),可以使用滚动数组,并且DP第一位一定为j。
滚动数组太丑了..考试的时候作死写一个然后惨遭爆零..
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #define ll long long #define INF 1e18 //#include<cmath> using namespace std; inline ll read() { ll bj=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')bj=-1; ch=getchar(); } ll ret=0; while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return ret*bj; } ll n,m,a,b,x[10005]={0},G[204]={0},sum[10004]={0},ave=0; ll f[10001][220]={0},q[100005]={0},head=0,tail=0,minn; void reset() { memset(q,0,sizeof(q)); memset(x,0,sizeof(x)); memset(G,0,sizeof(G)); memset(sum,0,sizeof(sum)); ave=0,minn=INF,head=1,tail=0; } void init() { reset(); m=read();n=read();a=read();b=read(); for(ll i=1;i<=m;i++)x[i]=read(),ave+=x[i]; for(ll i=1;i<=n;i++)G[i]=read(); ave/=m; for(ll i=1;i<=m;i++)sum[i]=sum[i-1]+(x[i]-ave)*(x[i]-ave); } void DP() { ll cla,last,stu; for(int i=0;i<=10000;i++)for(int j=0;j<=200;j++)f[i][j]=INF; f[0][0]=0; for(ll j=1;j<=n;j++) { head=1,tail=0; for(ll i=1;i<=m;i++) { if(i-a>=0) { if(f[i-a][j-1]!=INF) { while(f[i-a][j-1]-sum[i-a]*G[j]<=f[q[tail]][j-1]-sum[q[tail]]*G[j]&&head<=tail)tail--; q[++tail]=i-a; } } while(q[head]<i-b&&head<=tail)head++; if(head>tail)continue; f[i][j]=f[q[head]][j-1]+(sum[i]-sum[q[head]])*G[j]; if(i==m)stu=q[head]; } if(f[m][j]<minn) { minn=f[m][j]; cla=j; last=m-stu; } } printf("%lld %lld %lld\n",minn,cla,last); } int main() { ll tim=read(); while(tim--) { init(); DP(); } return 0; } /* 1 10 3 1 4 16 11 12 13 10 15 16 17 18 14 4 5 1 1 5 1 4 5 49684 8970 96420 53727 12295 815 */
相关文章推荐
- tyvj1305 最大子序和 【单调队列优化dp】
- 【DP】【单调队列】【NOI2005】瑰丽华尔兹
- hdu 3401 Trade(单调队列优化DP)
- HDU 4374 One hundred layer(DP+单调队列优化)
- HDU 1003 Max Sum + 单调队列优化dp解法
- 2016.4 半期 DP+单调队列优化 摘橘子
- Vijos1243----用单调队列优化的DP
- uva 1427(单调队列优化dp)
- HDU-3401:Trade(dp+单调队列优化)
- hdu 4362(单调队列优化dp)
- poj 3017 dp+单调队列优化
- 【日常学习】【二分】【单调队列优化线性DP】codevs3342 绿色通道题解
- BZOJ_2343_[Usaco2011 Open]修剪草坪 _单调队列_DP
- GYM-101572A Airport Coffee(DP+单调队列)
- dp专辑 R - Trade [ 单调队列]
- POJ 1821 单调队列优化DP
- CF185 div1 B. Cats Transport(单调队列斜率优化dp)
- NKOJ 3545 接近(DP+单调队列)
- 12170 - Easy Climb(DP+单调队列)
- 【大渣】【DP+单调队列优化】布丁