題外話: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; }
//一堆括號看的我眼疼