SRM 536 DIV 2

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];
   }
};


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章