版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40032278/article/details/82145227
div.1
T1
题意
现有n个盒子,每个盒子里分别有R个红球,G个绿球和B个蓝球。
可以进行一种把一个球从一个盒子放到另一个盒子的操作。
现要用这种操作使得每个盒子里都只有一种颜色的球。
求最小操作次数。若不能,输出-1.
思路
首先,把所有的球都放到假想的三个框中。代价为球的总数。
然后我们发现,每个框都有一种颜色的球不需要放到假想框中。这种颜色的球的数量要从总代价里扣除。
而因为假象的框不存在,所以我们实际上要在保证选多的同时,保证每种颜色至少有一个框是选他的。
这显然可以转化为一个DP过程
#include <bits/stdc++.h>
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 <bits/stdc++.h>
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;
}