51NOD1522&CF567F 上下序列/Mausoleum DP

來源:互聯網
上載者:User

標籤:get   def   str   位置   push   problem   set   bool   16px   

題目傳送門:http://codeforces.com/problemset/problem/567/F大致題意:你有$1$到$N$的所有正整數每個數兩個,現在需要你將它排成一個序列,使得序列為單峰序列(存在一個$j \in [1,2N]$滿足$a_1 \leq a_2 \leq .. \leq a_j \geq a_{j+1} ... \geq a_{2N}$),並且滿足輸入中給出的$K$個約束條件。$N \leq 35 , K \leq 100$ 
因為序列要滿足單峰,所以考慮從小到大在沒有加入數位序列位置的最左和最右加入元素,這樣序列將會一直滿足單峰性質
考慮狀態$f_{p,q}$表示左邊已經填了$p$個,右邊填了$q$個的方案(其實可以壓掉其中一維),考慮第$i$個數位轉移,有$3$種:
$a:$將這兩個$i$都放在序列最左邊;$b:$將這兩個$i$放在序列最右邊;$c.$將這兩個$i$一個放一邊。
對於$K$個約束條件我們可以在加入的時候直接判斷:當前加入的兩個數相等,沒加入的位置的數必定比當前加的數大,而其他已經填好的地方一定比當前的數小。
最後的答案是$\frac{\sum\limits_{i=0}^{2n}f_{i,2n-i}}{3}$,除3是因為對於最後一次加入,$abc$三種方案都是可行的,但是我們只能算一種。
注意判斷約束條件時的細節,約束條件的儲存可以使用類似鄰接表的方法,在加入約束條件時如加入無向邊一樣變成兩個約束條件,判斷起來會方便一些。
  1 #include<bits/stdc++.h>  2 #define int long long  3 using namespace std;  4   5 int ans[72][72] , numOp[72];  6   7 vector < int > num[72] , op[72];  8 map < string , int > opToNum;  9  10 bool ifOK(int l , int r , int que1 , int que2){ 11 //特別注意判斷que1位置與que2位置有聯絡的情況 12     for(int i = 0 ; i < numOp[que1] ; i++) 13         switch(op[que1][i]){ 14             case 1: 15                 if(num[que1][i] < r && num[que1][i] > l || num[que1][i] == que2) 16                     return 0; 17                 break; 18             case 2: 19                 if(num[que1][i] < r && num[que1][i] > l && num[que1][i] != que2) 20                     return 0; 21                 break; 22             case 3: 23                 if(!(num[que1][i] == que2)) 24                     return 0; 25                 break; 26             case 4: 27                 if(!(num[que1][i] <= r && num[que1][i] >= l || num[que1][i] == que2)) 28                     return 0; 29                 break; 30             case 5: 31                 if(!(num[que1][i] < r && num[que1][i] > l) || num[que1][i] == que2) 32                     return 0; 33         } 34     for(int i = 0 ; i < numOp[que2] ; i++) 35         switch(op[que2][i]){ 36             case 1: 37                 if(num[que2][i] < r && num[que2][i] > l || num[que2][i] == que1) 38                     return 0; 39                 break; 40             case 2: 41                 if(num[que2][i] < r && num[que2][i] > l && num[que2][i] != que1) 42                     return 0; 43                 break; 44             case 3: 45                 if(!(num[que2][i] == que1)) 46                     return 0; 47                 break; 48             case 4: 49                 if(!(num[que2][i] <= r && num[que2][i] >= l || num[que2][i] == que1)) 50                     return 0; 51                 break; 52             case 5: 53                 if(!(num[que2][i] < r && num[que2][i] > l) || num[que2][i] == que1) 54                     return 0; 55         } 56     return 1; 57 } 58  59 main(){ 60     opToNum.insert(make_pair(">" , 1)); 61     opToNum.insert(make_pair(">=" , 2)); 62     opToNum.insert(make_pair("=" , 3)); 63     opToNum.insert(make_pair("<=" , 4)); 64     opToNum.insert(make_pair("<" , 5)); 65     int N , K; 66     for(cin >> N >> K ; K ; K--){ 67         int a , b , t; 68         string s; 69         cin >> a >> s >> b; 70         t = opToNum.find(s)->second; 71         if(a == b) 72             if(t == 1 || t == 5){ 73                 cout << 0; 74                 return 0; 75             } 76             else 77                 continue; 78         num[a].push_back(b); 79         op[a].push_back(t); 80         num[b].push_back(a); 81         op[b].push_back(6 - t); 82         numOp[a]++; 83         numOp[b]++; 84     } 85     ans[0][0] = 1; 86     for(int i = 1 ; i <= N ; i++){ 87     //DP 88         for(int j = 2 * i ; j >= 2 ; j--) 89             if(ans[j - 2][2 * i - j] && ifOK(j , 2 * N - 2 * i + j + 1 , j , j - 1)) 90                 ans[j][2 * i - j] += ans[j - 2][2 * i - j]; 91         for(int j = 2 * i ; j >= 2 ; j--) 92             if(ans[2 * i - j][j - 2] && ifOK(2 * i - j , 2 * N - j + 1 , 2 * N - j + 1 , 2 * N - j + 2)) 93                 ans[2 * i - j][j] += ans[2 * i - j][j - 2]; 94         for(int j = 1 ; j < 2 * i ; j++) 95             if(ans[2 * i - j - 1][j - 1] && ifOK(2 * i - j , 2 * N - j + 1 , 2 * i - j , 2 * N - j + 1)) 96                 ans[2 * i - j][j] += ans[2 * i - j - 1][j - 1]; 97     } 98     int all = 0; 99     for(int i = 0 ; i <= 2 * N ; i++)100         all += ans[i][2 * N - i];101     cout << all / 3;102     return 0;103 }

 

51NOD1522&CF567F 上下序列/Mausoleum DP

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.