【状压DP】作业
題目大意
有n個數,讓你對其排列,令排列后的第i個數字為sis_isi?,該排列要滿足:
輸出方案數
解題思路
設fs,if_{s,i}fs,i?為狀態為s,最后一個數為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; }總結
- 上一篇: 散列表知识点总结
- 下一篇: 西风显卡全面上架京东自营,RTX 406