最長序列問題,n皇后問題

2021-10-25 09:52:31 字數 4422 閱讀 4986

輸入輸出

題目: 最大子列和

題目: n皇后問題

題目:圖的著色問題

給定乙個長度為n的數列,求數值嚴格單調遞增的子串行的長度最長是多少。
輸入格式

第一行包含整數n。

第二行包含n個整數,表示完整序列。

輸出格式

輸出乙個整數,表示最大長度。

資料範圍

1≤n≤1000,

−10^9≤數列中的數≤10^9

輸入樣例:

73 1 2 1 8 5 6

輸出樣例:

4

解法: 動態規劃 o(n^2)
狀態表示: f[i] 表示從第乙個數字開始算, 以w[i] 結尾的最大上公升子串行(就是以w[i] 結尾的構成上公升子串行中長度最長的乙個序列長度)。

狀態計算: f[i] 是根據上面的定義, 第i個數結尾, 我們考慮i-1個數是什麼, 分析得i-1 個數有i 種情況(要麼是沒有數(就只有自己), 要麼是第1個數, 要麼是第二個數,…)

狀態計算: j 是表示i - 1 位,f[j] 表示 以i 結尾的 前一位上公升子串行的最長子序列, 如果w[i] > w[j] 時, f[i] = max(f[i], f[j] + 1); 如果前面沒有比w[i] 小的, f[i] 為1 (就是只含有自己乙個元素資料)。

最後找f[i] 的最大值。

動態規劃時間複雜度 = 狀態數量(幾維) * 計算每個狀態需要的時間(遍歷)

此題: n * n

ac**如下:

#include

#include

using

namespace std;

const

int n =

1010

;int a[n]

, f[n]

;int n;

intmain()

cout << re <

return0;

}

資料範圍

1≤n≤100000, // 資料範圍更改加大

−10^9≤數列中的數≤10^9

解法 動他規劃 o(nlogn)
此題資料範圍變大,用之前的解法 是會超時的。

因為之前求的 每種長度最長上公升子串行都存了很多, 我們只需要存下每種長度上公升子串行結尾最小的就行了。

我們這裡用二分找前面的最長子序列, 可以讓前面的是單調上公升序列。

#include

using

namespace std;

const

int n =

100010

;int a[n]

;// 儲存上面的樣例

int q[n]

;// 儲存每種長度的最長上公升子串行的長度

int n;

intmain()

len =

max(len, r +1)

; q[r +1]

= a[i];}

cout << len << endl;

return0;

}

輸入乙個 非空 整型陣列,陣列裡的數可能為正,也可能為負。

陣列中乙個或連續的多個整數組成乙個子陣列。

求所有子陣列的和的最大值。

要求時間複雜度為o(n)。

輸入:

81 -2 3 10 -4 7 2 -5

輸出:18

解法: 動態規劃
s這個變數中儲存的是以前乙個數結尾的子陣列中,和最大的是多少如果s <= 0,那麼就將s置為0,因為可能存在負數,不能將負收益的s加進來

如果s > 0,就讓s += x。

因為是求最大值,所以res的初值置為 無窮小int_min。同時,每一次迭代,都要更新res,也就是res = max(res, s)。最後返回的res就是 最大值。

時間複雜度: 將nums陣列中的所有元素都遍歷了一遍,所以是o(n)

ac**如下:

#include

#include

// int_min 檔案

using

namespace std;

const

int n =

100010

;int a[n]

;int n;

intmain()

cout << re ;

return0;

}

n-皇后問題是指將 n 個皇后放在 n∗n 的西洋棋棋盤上,使得皇后不能相互攻擊到,

即任意兩個皇后都不能處於同一行、同一列或同一斜線上。

現在給定整數n,請你輸出所有的滿足條件的棋子擺法。

輸入格式

共一行,包含整數n。

輸出格式

每個解決方案佔n行,每行輸出乙個長度為n的字串,用來表示完整的棋盤狀態。

其中」.」表示某乙個位置的方格狀態為空,」q」表示某乙個位置的方格上擺著皇后。

每個方案輸出完成後,輸出乙個空行。

輸出方案的順序任意,只要不重複且沒有遺漏即可。

資料範圍

1≤n≤9

輸入樣例:

4輸出樣例:

.q..

...q

q...

..q.

..q.

q...

...q

.q..

解法: 回溯 - 剪枝 o(n!)

其實這個搜尋可以與全排列的問題類似, 然後加上剪枝(刪除全排列中不符合條件中的情況)

見下面的**

對角線 dg[u+i]dg[u+i],反對角線udg[n−u+i]udg[n−u+i]中的下標 u+iu+i和 n−u+in−u+i 表示的是截距

下面的(x,y)(x,y)相當於(u,i)(u,i)

(1)反對角線 y=x+by=x+b, 截距 b=y−xb=y−x,因為我們要把 bb 當做陣列下標,所以 bb 不能是負的,所以我們 +n+n,保證是結果是正的

(2)而對角線 y=−x+by=−x+b, 截距是 b=y+xb=y+x,這裡截距一定是正的,所以不需要加偏移量

主要過程是: 先將點試探放上去, 然後下去遍歷後面的點,如果不行的話,返回上面,然後將之前的點恢復成上面的狀態。

ac**
// 按照全排列的方式

#include

using

namespace std;

const

int n =20;

// 因為對角線有正對角線和飯對角線, 這裡*2

// bool陣列用來判斷搜尋的下乙個位置是否可行

// col列,dg對角線,udg反對角線

// g[n][n]用來存路徑

int n;

char g[n]

[n];

bool col[n]

, dg[n]

, udg[n]

;void

dfs(

int u)

//對n個位置按行搜尋

for(

int i =

0; i < n; i ++

)// 剪枝(對於不滿足要求的點,不再繼續往下搜尋) udg[n - u + i],+n是為了保證大於0

// y = x+b ( y = -x +b) 我們求b= y-x +n(這裡的n是偏移量,保證b是正數) (b = y+x)if(

!col[i]

&&!dg[u + i]

&&!udg[n - u + i]

)// 按照行,已經滿足了每一行, 所以這裡在判斷剩下的三個情況就行了

}int

main()

解法:
ac**
在這裡插入**片
個人如果再刷解答劍指上的題目,可以加我v,共同進步吧~~~

連續正面的最長序列問題

設想你拋一枚硬幣n次,你期望看到的連續正面的最長序列是多長?這是演算法導論第四章裡的乙個問題,今天看了好久,才明白過來,在這裡做個記錄。書上從兩個不同的角度分析了這個問題,乙個是從概率的角度,通過計算這個序列長度的上界和下界推導出序列長度,乙個是利用書上所說的指示隨機變數 indicator ran...

N皇后問題

include define maxqueens 20 define minqueens 4 enum bool typedef struct queendata queendata queendata queens maxqueens 1 int ncount init int init chec...

N皇后問題

採用遞迴回溯法 執行結果 輸入8 對於n皇后解的個數,參考 當n 16時,構造法給出解,參考poj 3239 一 當n mod 6 2 且 n mod 6 3時,有乙個解為 2,4,6,8,n,1,3,5,7,n 1 n為偶數 2,4,6,8,n 1,1,3,5,7,n n為奇數 上面序列第i個數為...