当前位置: 代码迷 >> 综合 >> TopCoder SRM475 Div1 level three - RabbitProgramming题解(DP+枚举)
  详细解决方案

TopCoder SRM475 Div1 level three - RabbitProgramming题解(DP+枚举)

热度:46   发布时间:2024-02-12 17:18:33.0

题目传送门
下面将给出一系列提示,请尝试根据提示独立解决此问题。当然你也可以跳过。
提示1:
枚举选进队的最后一名的成绩


提示2:
什么时候一个兔子一定达到了“qualified”个,什么时候不可能进队?


提示3:
是否可以一只兔子一只兔子的检验是否一定达到前qualified 个的分数,或可能入队,一定不入队。。。


提示4:
是否可以把当前入队的兔子个数,达到前qualified 个的最少人数作为dp状态?


题解

首先常规套路,对于分数分组的题目可以让达线的人分数尽可能的高,其他的尽可能的低。设 m a i i m i i i ma_i表示第i只兔子最大可能分数,mi_i表示第i只兔子最小可能分数
枚举最后一个入队的兔子的编号,然后考虑能有多少种可能。那么什么样的情况是不可能的呢?

  1. 假设队中的最后一名为 x x ,其中 i i 在队中,如果 m a i < m a x ma_i<ma_x 则一定不可能,这样就违背了最后一名的定义
  2. 如果x为队中的最后一名,那么达线人数大于qualified 。

这两个条件只需要一个好的状态就可以解决 d p i , j , k dp_{i,j,k} 考虑前i只兔子,第j只为选中的队中最后一名,至少k名达线的方案数。
code:

/* {AuThOr Gwj */
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*} */
const int MAXN=55;
int mi[MAXN],ma[MAXN];
LL dp[MAXN][MAXN][MAXN];//考虑前i个,选入队的人,达到分数线的人数 
class RabbitProgramming{public:long long getTeams(vector<int> points,vector<string> standings,int q,int s){/*SOLUTION :枚举选中队伍的最后一名是多少 */int n=standings.size();rep(i,points.size()){if(points[i]<0){rep(j,n)if(standings[j][i]=='Y'){ma[j+1]-=points[i];}}else{rep(j,n)if(standings[j][i]=='Y')ma[j+1]+=points[i],mi[j+1]+=points[i];} }
// rb(i,1,n)
// cout<<ma[i]<<" "<<mi[i]<<endl; LL rest=0;rb(x,1,n){memset(dp,0,sizeof(dp));dp[0][0][0]=1;	rb(i,1,n){rb(j,0,s)rb(k,0,q){if(i==x){if(j&&k)dp[i][j][k]=dp[i-1][j-1][k-1];}	else{if(i<x){if(mi[i]>=ma[x]){if(k){dp[i][j][k]=dp[i-1][j][k-1];if(j)dp[i][j][k]+=dp[i-1][j-1][k-1];}}else{if(ma[i]>=ma[x]){if(j&&k){dp[i][j][k]=dp[i-1][j-1][k-1];}} dp[i][j][k]+=dp[i-1][j][k];}}else{if(mi[i]>ma[x]){if(k){dp[i][j][k]=dp[i-1][j][k-1];if(j)dp[i][j][k]+=dp[i-1][j-1][k-1];}}else{if(ma[i]>ma[x]){if(j&&k){dp[i][j][k]=dp[i-1][j-1][k-1];}} dp[i][j][k]+=dp[i-1][j][k];}}}}}rb(i,s,q){
// cout<<x<<"-"<<s<<"-"<<i<<"-"<<dp[n][s][i]<<endl;rest+=dp[n][s][i];}}return rest;}			
};

同一类问题:
传送门

  相关解决方案