ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2016 多校5 ATM

2020-08-31 10:01:45  阅读:283  来源: 互联网

标签:10 cmin int rep ATM 多校 决策 2016 dp


2016 多校5 ATM

题意:

有个人富到不知道自己有多少钱,但是知道钱数\(x\in \Z \cap [0,K]\)

它最多可以有\(W\)次查询超过钱数,\(W\ge 1\)

要求在最优决策的情况下,最小次数取出所有钱的期望次数

\[\ \]

设\(K,W\)上界为\(O(n)\)

先考虑边界情况,如果它手里有\(0\)块钱,那么需要查询一次才知道自己吃土了

如果手头\(W=1\),那么只能每次取\(1\),否则就可能被抓走

众所周知,情况个数有限的期望问题,可以先直接计数然后除掉情况数,所以

定义\(dp_{i,j}\)为已知手头的票子上限\(i\),且还剩\(j\)次会被抓去干奇怪的事情的最小代价总和

对于\(j>1\)的情况,我们需要决策这一次选出多少钱

假设这一次我们选择取出\(k\)块钱

1.那么对于实际钱数为\([0,k-1]\)的部分,查询会超限,并且知道上界变为\(k-1\)

2.对于实际钱数\([k,i]\)的部分,上界变为\(i-k\)

而这次决策产生的代价要计算所有情况的代价,即为\(i+1\)

因此,转移的表达式应是\(\begin{aligned} dp_{i,j}=\min_{k=1}^i\lbrace dp_{k-1,j-1}+dp_{i-k,j}+i+1\rbrace\end{aligned}\)

因为不是期望而是计数,决策应该更好理解了吧

直接转移,复杂度为\(O(n^3)\)

优化1

不会证明,但是\(dp_{k-1,j-1}+dp_{i-k,j}\)构成了关于\(k\)的 斜率单调非递减的函数(俗称单峰函数),可以直接三分

复杂度为\(O(n^2\log n)\)

#include<bits/stdc++.h>
using namespace std;
typedef long double ldb;
#define reg register
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
template <class T> inline void cmin(T &a,const T &b){ ((a>b)&&(a=b)); }

const int N=2e3+10;
 
int n,m;
int dp[N][N];
 
int main(){
    rep(i,1,N-1) dp[1][i]=2;
    rep(i,1,N-1) dp[i][1]=i*(i+1)/2+i;
    rep(i,2,N-1) rep(j,2,N-1) {
        dp[i][j]=1e9;
        int l=1,r=i;
        cmin(dp[i][j],dp[0][j-1]+dp[i-1][j]+i+1);
        cmin(dp[i][j],dp[i-1][j-1]+dp[0][j]+i+1);
        while(l<r) {
            int a=(l+r)>>1,b=a+1;
            int x=dp[a-1][j-1]+dp[i-a][j]+i+1,y=dp[b-1][j-1]+dp[i-b][j]+i+1;
            cmin(dp[i][j],x),cmin(dp[i][j],y);
            if(x>=y) l=b;
            else r=a;
        }
    }
    while(~scanf("%d%d",&n,&m)) printf("%.6Lf\n",(ldb)dp[n][m]/(n+1));
}
 
 

优化2

感性理解,钱的上界越大,显然我们每次最优决策要取出的也就越多

即\(dp_{i,j}\)的最优决策位置关于\(i\) 单调非递减

由于转移的式子比较奇怪,这个题目不好使用决策单调性的分治优化方法(或许很简单吗)

但是由于转移是一个单峰函数,不存在波动的问题,所以可以直接记录决策位置\(g_{i,j}\)

或者说,就是单峰函数的最值位置是递增的,每次从\(g_{i-1,j}\)的最优位置开始向后找到\(g_{i,j}\)的峰的位置即可停止

对于每个\(j\),\(g_{i,j}\)最多从\(1\)移动到\(K\),所以复杂度为\(O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
typedef long double ldb;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
template <class T> inline void cmin(T &a,const T &b){ ((a>b)&&(a=b)); }
 
const int N=2e3+10;
 
int n,m;
int dp[N][N],G[N][N];
 
int main(){
    rep(i,1,N-1) dp[1][i]=2;
    rep(i,1,N-1) dp[i][1]=i*(i+1)/2+i;
    rep(i,2,N-1) rep(j,2,N-1) {
        dp[i][j]=1e9;
        rep(k,max(G[i-1][j],1),i) { // 从上一个决策位置开始for
            int x=dp[k-1][j-1]+dp[i-k][j]+i+1;
            if(x<=dp[i][j]) G[i][j]=k,dp[i][j]=x;
            else break;
        }
    }
    while(~scanf("%d%d",&n,&m)) printf("%.6Lf\n",(ldb)dp[n][m]/(n+1));
}
 
 

优化3:第二维大小的优化

我们知道,存在一种决策方法即每次二分上界,可以取到一个较优值

满足这个决策只需要\(W\ge \log_2 k\),大致可以认为\(W\ge 10\)

在最优决策的情况下,一定可以在\(10\)次错误的范围内查出结果,即\(W\ge 10\)之后\(W\)的值已经不会影响答案了

所以直接上优化,转移复杂度就是\(O(n^2\log n)\)

加上决策单调性的优化,就是\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define reg register
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
template <class T> inline void cmin(T &a,const T &b){ ((a>b)&&(a=b)); }

const int N=2e3+10;

int n,m;
int dp[N][11],G[N][11];

int main(){
    rep(i,1,10) dp[1][i]=2;
    rep(i,1,N-1) dp[i][1]=i*(i+1)/2+i;
    rep(i,2,N-1) rep(j,2,10) {
        dp[i][j]=1e9;
        rep(k,max(G[i-1][j],1),i) {
            int x=dp[k-1][j-1]+dp[i-k][j]+i+1;
            if(x<=dp[i][j]) G[i][j]=k,dp[i][j]=x;
            else break;
        }
    }
    while(~scanf("%d%d",&n,&m)) printf("%.6lf\n",1.0*dp[n][min(m,10)]/(n+1));
}

以下是来自地狱的魔改代码

#include<cstdio>
#define rep(i,a,b) for(i=a;i<=b;++i)
enum{N=2000};
int n,m,dp[11][N|1],i,j,k,x;
main(){
	rep(i,1,N) dp[1][i]=i*(i+1)/2+i;
	rep(j,2,10) rep(i,dp[j][k=1]=2,N) {
		dp[j][i]=1e9;
		for(;k<=i && (x=dp[j-1][k-1]+dp[j][i-k]+i+1)<=dp[j][i];++k) dp[j][i]=x;
		--k;
	}
	while(~scanf("%d%d",&n,&m))printf("%.6lf\n",1.0*dp[m>10?10:m][n]/(n+1));
}

标签:10,cmin,int,rep,ATM,多校,决策,2016,dp
来源: https://www.cnblogs.com/chasedeath/p/13588052.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有