TopCoder SRM 568

div.1

T1

题意

现有n个盒子,每个盒子里分别有R个红球,G个绿球和B个蓝球。
可以进行一种把一个球从一个盒子放到另一个盒子的操作。
现要用这种操作使得每个盒子里都只有一种颜色的球。
求最小操作次数。若不能,输出-1.

思路

首先,把所有的球都放到假想的三个框中。代价为球的总数。
然后我们发现,每个框都有一种颜色的球不需要放到假想框中。这种颜色的球的数量要从总代价里扣除。
而因为假象的框不存在,所以我们实际上要在保证选多的同时,保证每种颜色至少有一个框是选他的。
这显然可以转化为一个DP过程

#include 
using namespace std;
int c[200],dp[200][10];
class BallsSeparating {
public:
int minOperations( vector <int> red, vector <int> green, vector <int> blue ) ;
};
int BallsSeparating::minOperations(vector <int> red, vector <int> green, vector <int> blue) {
	int n=red.size(),tot=0,i,j;
	memset(c,0,sizeof(c));
	if(n<3) return -1;
	for(i=0;i<n;i++) 
	{
		c[i]=max(red[i],max(green[i],blue[i]));
		tot=tot+red[i]+green[i]+blue[i];
	}
	memset(dp,0,sizeof(dp));
	dp[0][1]=red[0];
	dp[0][2]=green[0];
	dp[0][4]=blue[0];
	for(i=1;i<n;i++)
	{
		for(j=1;j<=7;j+=2) 
			dp[i][j]=max(dp[i][j],max(dp[i-1][j]+red[i],dp[i-1][j^1]+red[i]));
		for(j=2;j<=7;j++)
		{
			if(j&2) dp[i][j]=max(dp[i][j],max(dp[i-1][j]+green[i],dp[i-1][j^2]+green[i]));
		}
		for(j=4;j<=7;j++)
			dp[i][j]=max(dp[i][j],max(dp[i-1][j]+blue[i],dp[i-1][j^4]+blue[i]));
	}
	if(dp[n-1][7]<0) return -1;
	else return tot-dp[n-1][7];
}

T2

题意

Sum(A,P)= A [0,P [0]] + A [1,P [1]] + … + A [N-1,P [N-1]]
A [i,j]是第i行和第j列中A的元素 P是从0到N-1的整数的排列
如果Sum(A,P)总是等于相同的值而忽略了排列P的选择,则矩阵A符合要求
输出 这种矩阵的数量

div.2

T3

题意

有n张卡片 上面有一些数字,排序他们使得其为一个非递减序列,,在分类过程中将执行步骤1(卡组的随机播放)的预期次数。

思路

反着处理一个dp就好了。只需要思考,倒着取数的期望就是当前数/相同数+之前数-1。。。然后dp前排个序就好了。

#include 
using namespace std;
class ShuffleSort {
public:
double shuffle( vector <int> cards ) ;
};
double ShuffleSort::shuffle(vector <int> cards) {
	int n=cards.size(),i,x=0,tot,k;
	double ans=0.0;
	tot=n;
	sort(cards.begin(),cards.end());
	while(x<n)
	{
		k=0;
		for(i=x;i<n;i++)
			if(cards[i]==cards[x]) k++;
		x+=k;
		while(k>0)
		{
			ans=ans+(double)tot/k-1.0;
			tot--;
			k--;
		}
	}
	ans+=1.0;	
	return ans;
}

你可能感兴趣的:(TopCoder,题解)