• 【Codeforces #142 Div1】Solutions


    A、B、C题题解请移步http://www.cnblogs.com/Delostik/archive/2012/10/03/2710655.html

      

    【D. Towers】

      http://www.codeforces.com/contest/229/problem/D

      题目大意:有n座塔,每次操作可以将第i座塔和第(i-1)座或第(i+1)座合并,新塔高度为两塔高度和。问最少多少次操作之后使得塔高度序列不降。

      O(n^2)的方法:f[i]表示使前i座塔高度不降的最少操作次数,h[i]表示在执行f[i]操作的前提下,第i座塔(或者是由操作i合并成的新塔)的最小高度。

         f[i]=min{f[j]},sum(j,i)>=h[j-1],0≤j≤i ; h[i]=sum(j,i)

      预处理前缀和,枚举i,j,完毕。

      里面用到一个贪心性质就是,离i最近的j肯定是最优的……因为如果有状态j'<j,f[j]=f[j'],那么h[j']>h[j]这是显然的……这就没必要了……

      有人说单调队列……其实用单调队列实质上也是要枚举,没看出有什么实质性的不一样……

    #include <iostream>
    using namespace std;
    
    int n,H,f[5010],sum[5010],h[5010];
    
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		cin>>H;
    		sum[i]=sum[i-1]+H;
    	}
    	for(int i=1;i<=n;i++)
    		for(int j=i-1;j>=0;j--)
    			if(sum[i]-sum[j]>=h[j]){
    				f[i]=f[j]+i-j-1;
    				h[i]=sum[i]-sum[j];
    				break;
    			}
    	cout<<f[n]<<endl;
    }
    

    【E. Gifts】

      http://www.codeforces.com/contest/229/problem/E

      题目大意:有一些礼物,有些礼物有相同的名字单有不同的价格,有些礼物有相同的价格但可以有不同的名字。人喊一个礼物的名字,便会随机得到叫这个名字的其中一个礼物。问取得n个最大价值的礼物的概率是多少。

      “名字相同的礼物有不同的价格”,这句话很重要。我们确定一个价值下限minv,那么在所有礼物里面有两类,一类是一定要选的(v[i]>minv),另一类是价值恰好等于minv,可能选其中的一部分。那句话就告诉我们,在每种名字的礼物中,最多有1个是可以选择“选”或者“不选”的。

      于是我们把第二类挑出来单独搞,称它们为“可选礼物”。可知可选礼物个数choose=n-cnt个,cnt为价值大于minv的礼物数量。

      f[i][j]表示前i种名字的礼物中,选取了j个可选的礼物。num[i]表示名字为i个礼物个数,must[i]表示名字为i的礼物中的必选礼物个数。

      转移:1.若第i种名字的礼物中没有可选礼物,那么f[i][j]=f[i-1][j]/C(must[i],num[i])

         2.若第i种名字的礼物中有可选礼物,那么令t=(n-cnt-j)/choose,表示在第i种礼物中选取一个可选礼物的概率。

        f[i][j]=f[i-1][j]/C(must[i],num[i])*(1-t)     在i种中不选可选礼物

        f[i][j+1]=f[i-1][j]/C(must[i],num[i]+1)*t   在i种中选可选礼物

    #include <iostream>
    #include <vector>
    #include <iomanip>
    #include <algorithm>
    #define mn 1010
    using namespace std;
    
    vector<int> v[mn];
    int n,m,x,minv,choose,cnt,tot,a[mn],must[mn],num[mn];
    double C[mn][mn],f[mn][mn],tmp;
    bool prob[mn];
    
    int main(){
    	for(int i=0;i<=1000;i++){
    		C[i][0]=1;
    		for(int j=1;j<=i;j++)
    			C[i][j]=C[i-1][j]+C[i-1][j-1];
    	}
    	cin>>n>>m;
    	for(int i=1;i<=m;i++){
    		cin>>num[i];
    		for(int j=1;j<=num[i];j++){
    			cin>>x;
    			v[i].push_back(x);
    			a[++tot]=x;
    		}
    	}
    	sort(a+1,a+1+tot);
    	minv=a[tot-n];
    	for(int i=1;i<=m;i++){
    		for(int j=0;j<v[i].size();j++)
    			if(v[i][j]>minv) cnt++,must[i]++;
    			else if(v[i][j]==minv) prob[i]=true;
    		choose+=prob[i];
    	}
    	f[0][0]=1;
    	for(int i=1;i<=m;i++){
    		for(int j=0;j<=n-cnt;j++)
    			if(!prob[i]) f[i][j]=f[i-1][j]/C[num[i]][must[i]];
    			else{
    				tmp=(double)(n-cnt-j)/choose;
    				f[i][j]+=f[i-1][j]/C[num[i]][must[i]]*(1-tmp);
    				f[i][j+1]+=f[i-1][j]/C[num[i]][must[i]+1]*tmp;
    			}
    		choose-=prob[i];
    	}
    	cout<<fixed<<setprecision(10)<<f[m][n-cnt]<<endl;
    }
    
  • 相关阅读:
    【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-7 混合概率密度
    【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-6 直接光源采样
    【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-5 random direction & ONB
    【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-4 基于重要性采样的材质初探
    【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-3 蒙特卡罗 (三)
    区域生长算法 全局分类 C++ & matlab
    智能优化 之 下山单纯形法 C++
    图形暂时停更
    【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-2 蒙特卡罗(二) 重要性采样
    【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-1 蒙特卡罗 (一)
  • 原文地址:https://www.cnblogs.com/Delostik/p/2710670.html
Copyright © 2020-2023  润新知