JZYZOJ 1388 旅遊 狀壓dp
阿新 • • 發佈:2017-11-05
進行 tdi namespace 簡單 從後往前 ble con pan target
據此,f[i]表示狀態i(i上為1的位表示這一位的人放到隊列裏了)有多少種方案,a[x]表示x需要哪些人在前面(我寫的用的是後面,畢竟從後往前和從前往後並沒有什麽區別…)。
第一次交爆了long long,果然long long是1A率的攔路虎,努力克服
代碼
http://172.20.6.3/Problem_Show.asp?id=1388
求拓撲排序方案數 狀壓dp,最開始以為是拓撲排序加數論或者搜索,沒想到是狀壓dp,突然氣死.jpg; 完全沒有想到狀態轉移的方法,syq大佬太神了orz; 寫的時候太沈迷與topsort對人順序的分組類似於斯特林數求方案數(後來發現不是),忘了最原始的滿足條件(事件a在事件b前完成)即可增加方案數的簡單dp……(慚愧) 所以正解就是按dp進行順序向狀態裏加人,對人實現排序,顯然如果必須在a前的人都加到隊列裏了(我這裏用的是a後,嗯因為寫的時候是直接看syq大佬的代碼,其實我覺得記錄a前的更符合邏輯)那麽a就可以放到這個隊列後面了。1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7View Codeusing namespace std; 8 const int maxn=30; 9 int n,m; 10 int a[maxn]={}; 11 long long f[(1<<17)+10]={}; 12 int main(){ 13 scanf("%d%d",&n,&m);int x,y; 14 for(int i=1;i<=m;i++){ 15 scanf("%d%d",&x,&y); 16 a[x]|=(1<<(y-1)); 17 } 18 int ma=1<<n;f[0]=1; 19 for(int i=1;i<ma;i++){ 20 for(int j=0;j<n;j++){ 21 if((1<<j)&i){ 22 y=i-(1<<j); 23 if((a[j+1]&(~y))==0){ 24 f[i]+=f[y]; 25 } 26 } 27 } 28 } 29 printf("%I64d\n",f[ma-1]); 30 return 0; 31 }
JZYZOJ 1388 旅遊 狀壓dp