這道題,黑書上p257有解題的分析,之前沒看明白~~,網上搜了一大堆
看了這兩位大牛的報告
題目的大意就是一些裝飾欄,編號為1,2,3,...,n,他們的排列要遵循每個柵欄的編號要麼同大於相鄰的柵欄編號(a(i)>a(i-1), a(i) > a(i+1)),要麼同小於相鄰的柵欄編號(a(i) < a(i-1), a(i) < a(i+1))。按這種方式的每種排列按字典序排放,每種排列有乙個編號,從小到大,現在給出柵欄的個數,排列的序號,要你求出這個序號對應的排列布局。
動態規劃+計數
看了黑書上的感覺前面的敘述講得很模糊甚至感覺不對。。。。就後面的結論是對的,但是他又沒解釋那個g[n][t].up = sum(g[n-1][i].dowm)(t<=i<=n-1),為啥是i是從t開始的,還是看了某大牛的才明白,,,就是個對應關係,不考慮絕對高度,只考慮相對的高度
比如在1,2,3,4,5裡面選了3,那麼剩下1,2,4,5,因為只考慮相對高度,所以可以對應為1,2,3,4所以後面的n-1長從3開始
設dp[i][j][0]表示以i開頭,長度為j,頭兩塊板子是上公升的排列數
dp[i][j][1]表示i開頭,長度為j,頭兩塊板子是下降的排列數
那麼dp[i][j][0] = sum(dp[k][j-1][1]) i =< k <= j-1
dp[i][j][1] = sum(dp[k][j-1][0]) 1<=k dp[1][1][0] = dp[1][1][1] = 1
這樣就求出了dp[i][n][1]和dp[i][n][0]
那後看序號c出現在哪個段中這些段為排列為
dp[1][n][1], dp[1][n][0]
dp[2][n][1], dp[2][n][0]
.....
dp[n][n][1], dp[n][n][0]
若c出現在dp[i][n][1], dp[i][n][0]這個段中
求出c在這個段中的第幾個c = c - sum sum = (dp[1][n][1] + dp[1][n][0] + ... + dp[i-1][n][1] + dp[i-1][n][0])
然後當c <= dp[i][n][1]說明c出現在dp[i][n][1]這個段裡面, 否則出現在dp[i][n][0]這個段裡面
因為dp[i][n][0] = sum(dp[k][n-1][1]) i =< k <= n-1,;
dp[i][n][1] = sum(dp[k][n-1][1]) 1=< k < i
所以按照字典序,從小到大列舉k,從1到0的順序列舉下降和上公升
儲存每個i
由於每次儲存的i是經過之前的那種1,2,3,4,5選出3後,剩下1,2,4,5對應於1,2,3,4的那種方法所確定的
所以輸出要返回對映為1---n的數
暴力搜尋。。。。
從1-n遍歷j,沒有輸出就ans[i]--,當ans[i]==0表示這個數是j,標記j已經被輸出,下次遍歷就不算進去
#include #include #include #include using namespace std;
const int maxn = 25;
long long dp[maxn][maxn][2], c;
int ans[maxn];
bool visited[maxn];
int k, n;
void init();
void solve();
void output();
int main()
return 0;
}void init()
}}void solve()
sum += (dp[i][tn][0] + dp[i][tn][1]);
}if(c <= dp[cur][tn][1])
flag = true;
else
tn--;
while(tn > 0)
c -= dp[i][tn][0];}}
else
c -= dp[i][tn][1];}}
tn--;
flag = !flag;
}}void output()}}
}printf("\n");
}
poj 1037 動態規劃 字典序第k大
題目大意 給定n個數字,規定一種 cute 排序 序列中的數字大小為嚴格的波浪形,即 a 0 a 1 a 2 a 3 或者 a 0 a 1 a 2 a 3 對於n個數字來說,可以構成多個cute序列,這些序列按照字典序進行排序,求出第k個序列。題目分析 一 求字典序的第i個排列 直接一位一位列舉答案...
BZOJ1037動態規劃
資料範圍很小,可以用4維儲存下前i個男孩j個女孩,從這一位往前的所有點中男 女的差最大為x,女 男為y的方案數 主動遞推 f i 1 j x 1 max y 1 0 f i j x y f i j 1 max x 1 0 y 1 f i j x y 最後答案為 sigma x sigma y f n...
poj1037 dp 排列計數
今天學習dp 看的是北大培訓的課件 看到了這道題 開始看的時候 就算知道是dp 也不知道怎麼去寫 後面看了ac 直接寫思路 c i k down 表示的是前i根木頭中 以k打頭陣的down總數 c i k up 表示的是 前i根木頭中 以k打頭陣的up總數 再寫這道題時 首先要知道怎麼去排列計數 直...