题意:给你n个数,求有多少种全排列,使得相邻两个数差的绝对值>k
(n<=15)
信心满满:这回不会再死了。。。。(状压DP啊)
然而。。。。(TM我不会写)
依然写了个dfs70分(算是不错了QAQ)
正解:以f[i][j]代表当前排列最后一个是i,j代表状态(排列中的数选/没选)
#include<cstdio> #include<iostream> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define int long long #define olinr return #define _ 0 #define love_nmr 0 #define DB double inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-f; ch=getchar(); } while(isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } inline void put(int x) { if(x<0) { x=-x; putchar('-'); } if(x>9) put(x/10); putchar(x%10+'0'); } int a[18]; int n; int k; signed main() { n=read(); k=read(); int ans=0; for(int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+n+1); do { for(int i=2;i<=n;i++) if(abs(a[i]-a[i-1])<=k) goto wmy; ans++; wmy:; }while(next_permutation(a+1,a+n+1)); //纯暴力啊 put(ans); olinr ~~(0^_^0)+love_nmr; }
de<cstdio> #include<iostream> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define int long long #define olinr return #define _ 0 #define love_nmr 0 #define DB double inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-f; ch=getchar(); } while(isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } inline void put(int x) { if(x<0) { x=-x; putchar('-'); } if(x>9) put(x/10); putchar(x%10+'0'); } int a[18]; int n; int k; int ans; bool vis[18]; inline void dfs(int dep,int now) { if(dep==n) { ans++; return; } for(int i=1;i<=n;i++) { if(!vis[i]&&abs(a[i]-now)>k) { vis[i]=true; dfs(dep+1,a[i]); vis[i]=false; } } } signed main() { n=read(); k=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) { vis[i]=true; dfs(1,a[i]); vis[i]=false; } put(ans); olinr ~~(0^_^0)+love_nmr; }
正解:
#include<cstdio> #include<iostream> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define int long long #define olinr return #define _ 0 #define love_nmr 0 #define DB double inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-f; ch=getchar(); } while(isdigit(ch)) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } inline void put(int x) { if(x<0) { x=-x; putchar('-'); } if(x>9) put(x/10); putchar(x%10+'0'); } int n; int k; int a[20]; int f[20][120505]; int ans; signed main() { n=read(); k=read(); for(int i=1;i<=n;i++) a[i]=read(),f[i][1<<(i-1)]=1; //初始化 for(int i=0;i<(1<<n);i++) { for(int j=1;j<=n;j++) { if(i&(1<<(j-1))) //当前状态有的 { for(int v=1;v<=n;v++) { if(!(i&(1<<(v-1)))) //当前状态没有的 { if(abs(a[j]-a[v])>k) //可以加入 { f[v][i|(1<<(v-1))]+=f[j][i]; //累计方案 } } } } } } for(int i=1;i<=n;i++) ans+=f[i][(1<<n)-1]; //统计所有方案 put(ans); olinr ~~(0^_^0)+love_nmr; }