题外话:c++
是很是颓废的博主spa
写题解也不在于能不能经过啦,主要是缓解颓废code
首先看到这个题,确定是能够暴力搜索的:get
不得不说这道题仍是很善良的,一波大暴力dfs,竟然有70pts:it
#include<bits/stdc++.h> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch>'9'||ch<'0') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } int n,k; int s[20]; long long ans; bool vis[20]; void dfs(int cnt,int nxt) { if(cnt==n) { ans++; return; } for(int i=1;i<=n;i++) { if(vis[i]) continue; if(abs(s[i]-nxt)>k) { vis[i]=1; dfs(cnt+1,s[i]); vis[i]=0; } } } int main() { n=read(); k=read(); for(int i=1;i<=n;i++) s[i]=read(); dfs(0,-k-1); printf("%lld",ans); return 0; }
想改记忆化,而后我发现我不会ast
滚回来从新考虑dp:class
将奶牛状压到一个二进制数中,第i位表示这头奶牛是否在队伍中;(突兀搜索
咱们设 \(dp[i][j]\) 表示当前状态为i,最后一个加入队伍的奶牛是j的方案数;二进制
考虑如何转移:im
设如今的状态为 \(dp[i][j]\)
考虑枚举下一个加入队伍的奶牛g是哪一只,那么首先确定要知足的,就是这只奶牛不能已经加入队伍了 (奶牛:我有分身术 也就是i&(1<<(g-1))==0
1.若是已经在队伍里,显然要continue;(废话
2.若是不在队伍里,那么判断第g头奶牛和第j头奶牛之间的编号之差是否>k,一样的不是就continue掉 (一样的废话
若是上面两个条件都知足,那么就能够将g加入队伍,对应的状态 \(dp[i|(1<<(g-1))][g]+=dp[i][j];\)
考虑初始化:
对于只有一头奶牛的状况,显然只有一种方案,所以 \(dp[1<<(i-1)][i]=1;\)
而后由于上面讲的 很是很是之乱,我们来理一理思路:
首先显然是初始化,将只有一头奶牛的方案的值初始化为1
接下来枚举每一种状态
第二维枚举当前状态下,最后一个加入队伍的奶牛j是哪一只(能够直接从1~n枚举,用i&(1<<(j-1))!=0来判断合法与否
而后枚举下一头加入队伍的奶牛是哪一头,判断是否符合上面的两个条件,相应的进行修改
最后显然是输出答案啦:显然最后的答案应该是全部奶牛都加入了队伍,每一头奶牛最后进入队伍的方案数相加,也就是 \(\sum\limits_{i=1}^n dp[(1<<n)-1][i]\)
而后,大概应该可能就能够愉快的AC了?(是 码风清奇的奇女子,将就着看吧
#include<bits/stdc++.h> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch>'9'||ch<'0') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } int n,k; int s[20]; long long ans; long long dp[70000][18]; int main() { n=read(); k=read(); for(int i=1;i<=n;i++) s[i]=read(); for(int i=1;i<=n;i++) dp[1<<(i-1)][i]=1; for(int a=1;a<(1<<n);a++) { for(int j=1;j<=n;j++) { if(!(a&(1<<(j-1)))) continue; for(int g=1;g<=n;g++) { if((a&(1<<(g-1)))) continue; if(abs(s[j]-s[g])<=k) continue; dp[a|(1<<(g-1))][g]+=dp[a][j]; } } } for(int i=1;i<=n;i++) ans+=dp[(1<<n)-1][i]; printf("%lld\n",ans); return 0; }
//一堆括号看的我眼疼