SRM 536 DIV 2

来源:互联网 发布:软件包装盒 编辑:程序博客网 时间:2024/06/01 08:07

250pt.   BinaryPolynomialDivTwo  

纯英文阅读理解题,一坨英文,出题速度较慢。

 

500pt.   RollingDiceDivTwo          

先把每个字符串排好序,然后每列取最大的那个相加就行了。

 例如; {"137", "364", "115", "724"}

 对四个字符串排序

(1) 1 3 7

(2) 3 4 6

(3)1 1 5

(4)2 4 7

那么我们可以取每列的最大值 3 4 7 就行了。

 

1000pt. MergersDivTwo

先从小到大排好序,如果取得最大值,必然是连续地合并。

可以简单地理解下,比如有3个从小到大排好序的数a1,a2,a3

第一种先合并a1,a2,再合并a3.结果记为ans1

第二种先合并a1,a3,再合并a2.结果记为ans2

ans1-ans2=(a3-a2)/2>0;

设dp[i]表示前i项合并为一项所取得的最大值。

状态转移方程为

dp[i]=max(dp[i],(dp[i-j]+s[i]-s[i-j])/(j+t));   (j>=k-1 && j<=i ; )

表示前面的i-j个数已经合并为一个数,然后再合并[i-j+1,i ]这 j个数.

t记录dp[i-j]是否成立,成立就表示前面合并成功一个数。注意i-j==0的情况。

 

#include <iostream>#include <cstdio>#include <algorithm>#include <string>#include <vector>#include <cmath>using namespace std;const int inf = 2147483647;double dp[55];int a[55];int s[55];class MergersDivTwo{public:   double findMaximum(vector<int> revenues, int k)   {   int n=revenues.size();   for(int i=1;i<=n;i++)   a[i]=revenues[i-1];       sort(a+1,a+n+1);       for(int i=0;i<=n;i++)   dp[i]=-inf;       s[0]=0;   for(int i=1;i<=n;i++)   s[i]=s[i-1]+a[i];   dp[0]=0.0;       for(int i=1;i<=n;i++)   {      for(int j=k-1;j<=i;j++)  {  if(j==k-1 && i-j==0)  continue;  if(dp[i-j]!=-inf)  {  double t=1.0;                  if(i-j==0)                     t=0.0;                  dp[i]=max(dp[i],(dp[i-j]+s[i]-s[i-j])/(t+j));  }  }   }   return dp[n];   }};


 

 

 

原创粉丝点击