YbtOJ#20065-[NOIP2020模拟赛B组Day4]模拟比赛【dp】
生活随笔
收集整理的這篇文章主要介紹了
YbtOJ#20065-[NOIP2020模拟赛B组Day4]模拟比赛【dp】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
正題
題目鏈接:http://noip.ybtoj.com.cn/contest/90/problem/3
解題思路
有nnn道題,mmm個人。一些題目是讓某些人一定得分,一些題目是讓某些人可以能得分。
求排名前sss的人選出ttt個人,可能的集合個數(shù)。
解題思路
顯然我們?nèi)绻袛嘁粋€集合UUU能否被選擇,那么肯定是這個集合內(nèi)的人選最高分,其他的最低分。
那我們可以按照最高分數(shù)值從大到小排序,然后枚舉一個iii表示選擇這個iii且這個iii后面的都不選擇。那么這個iii肯定是這ttt個人里排名最后的,那么我們要從iii前面選t?1t-1t?1個然后要求大于iii的最大值的分數(shù)不到sss個,考慮dpdpdp這個iii前面的選擇方案。
設(shè)fi,j,kf_{i,j,k}fi,j,k?表示選到第iii個,現(xiàn)在選擇了jjj個,大于maximax_imaxi?的沒有選擇的minminmin值有kkk個的方案。
時間復(fù)雜度O(n4)O(n^4)O(n4)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=55; ll n,m,s,t,ans,a[N],mx[N],mi[N],p[N],f[N][N][N]; char str[N]; bool cmp(ll x,ll y) {return mx[x]>mx[y];} int main() {freopen("ctsc.in","r",stdin);freopen("ctsc.out","w",stdout);scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);scanf("%lld",&m);for(ll i=1;i<=m;i++){scanf("%s",str+1);for(ll j=1;j<=n;j++){if(a[j]<0)mx[i]+=-a[j]*(str[j]=='Y');else mx[i]+=a[j]*(str[j]=='Y'),mi[i]+=a[j]*(str[j]=='Y');}mx[i]=100*mx[i]+m-i;mi[i]=100*mi[i]+m-i;p[i]=i;}scanf("%lld%lld",&s,&t);sort(p+1,p+1+m,cmp);for(ll i=1;i<=m;i++){ll k=s-t;for(ll j=i+1;j<=m;j++)if(mx[p[i]]<mi[p[j]])k--;memset(f,0,sizeof(f));f[0][0][0]=1;for(ll j=1;j<i;j++)for(ll h=0;h<t;h++)for(ll g=0;g<=k;g++){//f[j][h][g]表示選到第i個,現(xiàn)在選了h個,有g(shù)個比它大 if(g&&mi[p[j]]>mx[p[i]])f[j][h][g]+=f[j-1][h][g-1];else if(mi[p[j]]<mx[p[i]]) f[j][h][g]+=f[j-1][h][g];if(h)f[j][h][g]+=f[j-1][h-1][g];}for(ll g=0;g<=k;g++)ans+=f[i-1][t-1][g];}printf("%lld",ans);return 0; }總結(jié)
以上是生活随笔為你收集整理的YbtOJ#20065-[NOIP2020模拟赛B组Day4]模拟比赛【dp】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国联通积分怎么兑换 兑换步骤是怎么样的
- 下一篇: YbtOJ#20066-[NOIP202