【状压DP】作业
題目大意
有n個數(shù),讓你對其排列,令排列后的第i個數(shù)字為sis_isi?,該排列要滿足:
輸出方案數(shù)
解題思路
設(shè)fs,if_{s,i}fs,i?為狀態(tài)為s,最后一個數(shù)為i的方案數(shù)
那么每次選擇一個可行的點轉(zhuǎn)移,最后取所有點都排列好的狀態(tài)即可
code
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 20 #define M 263000 #define wyc 4921057 using namespace std; int n,num,now,ans,a[N],b[N],v[N],f[M][N]; int main() {scanf("%d",&n);for(int i=1;i<=n;++i){scanf("%d",&a[i]);v[a[i]]++;}for(int i=1;i<=n;++i)scanf("%d",&b[i]);for(int i=2;i<=10;++i)v[i]+=v[i-1];for(int i=1;i<=n;++i)if(!v[a[i]-1])f[1<<i-1][i]=1;for(int s=1;s<(1<<n)-1;++s){num=0;for(int i=1;i<=n;++i)if(s&(1<<i-1))num++;for(int i=1;i<=n;++i)if(s&(1<<i-1)&&f[s][i]){now=0;for(int j=i+1;j<=n&&now<=b[i];++j)if(!(s&(1<<j-1))){if(a[j]==a[i]||a[j]>a[i]&&num==v[a[i]])(f[s|(1<<j-1)][j]+=f[s][i])%=wyc;now++;}now=0;for(int j=i-1;j>0&&now<=b[i];--j)if(!(s&(1<<j-1))){if(a[j]==a[i]||a[j]>a[i]&&num==v[a[i]])(f[s|(1<<j-1)][j]+=f[s][i])%=wyc;now++;}}}for(int i=1;i<=n;++i)(ans+=f[(1<<n)-1][i])%=wyc;;printf("%d",ans);return 0; }總結(jié)