【状压DP】滚榜(P7519)
正題
P7519
題目大意
n個隊伍,排名先按分數(shù)排序再按編號排序,每個隊伍有一個初始分數(shù) aia_iai?,和一個附加分數(shù) bib_ibi?
對于一個合法的 bib_ibi? 序列,按 bib_ibi? 大小排序,從小到大把每個 bib_ibi? 加進對應的 aia_iai? 中,且每個 bib_ibi? 加入后對應的點會成為排名第一的點
現(xiàn)在告訴你所有 bib_ibi? 的和 m,問你對于所有合法的 bib_ibi?,最后的排名有多少種
解題思路
考慮狀壓DP,設 fS,i,j,kf_{S,i,j,k}fS,i,j,k? 為當前所有點是否添加的狀態(tài)為 SSS,最后添加的點為 iii,bi=jb_i=jbi?=j,已經加了的 bbb 和為 kkk 的方案數(shù)
直接轉移時間復雜度為 O(2nn2m2)O(2^nn^2m^2)O(2nn2m2),會TLE
考慮到答案的計算之和最后的排名有關,也就是和加入 bbb 的順序有關(下文所有順序都是指加入順序中的先后),那么對于一種加入順序,讓所有點的 bib_ibi? 盡量小(除最后一個點)
因為 bib_ibi? 是單調遞增的,所以考慮一個點加入 bib_ibi? 時,讓后面點的 bbb 都加上 bib_ibi?,那么就可以保證 bib_ibi? 是單調遞增的
綜上,可以優(yōu)化掉最后添加的點 iii 的附加值 bib_ibi?,那么設 fS,i,kf_{S,i,k}fS,i,k? 表示狀態(tài)為S,最后添加的點為 iii ,bib_ibi? 的和為 kkk ,然后直接轉移即可
時間復雜度 O(2nn2m)O(2^nn^2m)O(2nn2m),因為很多狀態(tài)都跑不到,所以實際上能過
code
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 14 using namespace std; ll n,m,mx,sum,ans,a[N],f[1<<N][N][505]; int main() {scanf("%lld%lld",&n,&m);for(ll i=1;i<=n;++i){scanf("%lld",&a[i]);if(a[i]>a[mx])mx=i;}f[0][mx][0]=1;//要保證第一個點加到比最大的點大for(ll S=0;S<(1<<n)-1;++S){sum=0;for(ll i=1;i<=n;++i)if(!(S&(1<<i-1)))sum++;//計算后面有多少個點for(ll k=0;k<=m;++k)for(ll i=1;i<=n;++i) if(f[S][i][k])for(ll j=1;j<=n;++j)if(!(S&(1<<j-1)))if(k+sum*max(a[i]-a[j]+(j>i),0ll)<=m)f[S|(1<<j-1)][j][k+sum*max(a[i]-a[j]+(j>i),0ll)]+=f[S][i][k];}for(ll i=1;i<=n;++i)for(ll j=0;j<=m;++j)//多出來的部分放到最后一個點ans+=f[(1<<n)-1][i][j];printf("%lld",ans);return 0; }總結
以上是生活随笔為你收集整理的【状压DP】滚榜(P7519)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【平衡规划】Arithmetic Ope
- 下一篇: 攻城掠地武将装备搭配 快来看看