Topcoder 10880 - RabbitProgramming 题解
为叙述简便,把题中的 \(qualified\) 称为 \(k\), \(selected\) 称为 \(sel\)。
考虑一组(大小为 \(sel\) 的)兔子能被选中的条件。可以发现,当且仅当它们能同时排进前 \(k\) 时,它们有机会被选中。很明显,我们要让这 \(k\) 只兔子分数尽可能大,其它兔子分数尽可能小。
这个条件是否能满足,取决于这 \(sel\) 只兔子中最不给力的那只。所以,考虑枚举这只兔子,假设为 \(low\)。
那么 \(low\) 放在未选的兔子中的排名必然不大于 \(k - sel + 1\) 。
可以设计出\(dp\)状态:\(dp_{i,s,rnk}\) 表示考虑到第 \(i\) 只非 \(low\) 的兔子,选了 \(s\) 只兔子进队,当前 \(low\) 在未选的兔子中排名 \(rnk\) 的方案数。
转移有三种:
这只兔子最好情况下排在 \(low\) 前面,且进队了,转移到 \(dp_{i+1,s+1,rnk}\)
这只兔子最坏情况下排在 \(low\) 前面,而没进队,转移到 \(dp_{i+1,s,rnk+1}\)
这只兔子最坏情况下排在 \(low\) 后面,也没进队,转移到 \(dp_{i+1,s,rnk}\)
比较两只兔子谁在前,可以转化为二元组 \((score, -id)\) 再比大小(毕竟第二关键字要从小到大)
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mit map<int,int>::iterator
#define sit set<int>::iterator
#define itrm(g,x) for(mit g=x.begin();g!=x.end();g++)
#define itrs(g,x) for(sit g=x.begin();g!=x.end();g++)
#define ltype int
#define rep(i,j,k) for(ltype(i)=(j);(i)<=(k);(i)++)
#define rap(i,j,k) for(ltype(i)=(j);(i)<(k);(i)++)
#define per(i,j,k) for(ltype(i)=(j);(i)>=(k);(i)--)
#define pii pair<int,int>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back
#define fastio ios::sync_with_stdio(false)
#define check(x) if(x>=mod) x-=mod
const int inf=0x3f3f3f3f,mod=1000000007;
const double pi=3.1415926535897932,eps=1e-6;
void chmax(int &x,int y){if(x < y) x = y;}
void chmin(int &x,int y){if(x > y) x = y;}
int qpow(int x,int y){
int ret = 1;
while(y) {
if(y & 1) ret = (ll)ret * x % mod;
x = (ll)x * x % mod;
y >>= 1;
}
return ret;
}
int m,n,a[55],mx[55],mn[55],k,sel;
char st[55][55];
map<int,int> mp;
ll dp[55][55][55],ans;
ll mian()
{
//scanf("%d%d",&m,&n);
//rep(i,1,m) scanf("%d",a+i);
rep(i,1,n) {
//scanf("%s",st[i]+1);
rep(j,1,m) if(st[i][j] == 'Y') {
if(a[j] < 0) mx[i] -= a[j];
else mx[i] += a[j], mn[i] += a[j];
}
//printf("%d %d\n",mx[i],mn[i]);
}
//scanf("%d%d",&k,&sel);
rep(low,1,n) {
pii res = mpr(mx[low], -low);
dp[0][1][1] = 1;
rep(ii,0,n-2) rep(sel,1,n) rep(rank,1,n){
//int i = ii + (ii >= low);
int i = ii + 1 + (ii + 1 >= low);
pii x = mpr(mn[i], -i), y = mpr(mx[i], -i);
if(y > res) {
dp[ii + 1][sel + 1][rank] += dp[ii][sel][rank];
}
if(x < res) {
dp[ii + 1][sel][rank] += dp[ii][sel][rank];
}
else {
dp[ii + 1][sel][rank + 1] += dp[ii][sel][rank];
}
}
rep(i,1,k - sel + 1) ans += dp[n-1][sel][i];
rep(ii,0,n-1) rep(sel,1,n) rep(rank,1,n) dp[ii][sel][rank] = 0;
}
return ans;
}
class RabbitProgramming
{
public:
ll getTeams(vector<int> S,vector<string> ST,int K,int SEL) {
m = S.size();
n = ST.size();
k = K;
sel = SEL;
rap(i,0,m) a[i + 1] = S[i];
rap(i,0,n) rap(j,0,m) st[i + 1][j + 1] = ST[i][j];
return mian();
}
}cwk;
int main()
{
printf("%lld\n",cwk.getTeams({1},{"Y","Y","N"},1,1));
return 0;
}