思路**
0-1 揹包問題
思路**
素數環問題
思路**
二分查詢
0-1揹包問題
素數環問題
加1乘2平方
最長公共子串行
活動安排
描述
給定乙個單調遞增的整數序列,問某個整數是否在序列中。輸入
第一行為乙個整數n,表示序列中整數的個數;輸出第二行為n(n不超過10000)個整數;
第三行為乙個整數m(m不超過50000),表示查詢的個數;接下來m行每行乙個整數k。
每個查詢的輸出佔一行,如果k在序列中,輸出yes,否則輸出no。輸入樣例
5輸出樣例1 3 4 7 1133
69
yes二分查詢(binary search)也叫作折半查詢。二分查詢有兩個要求,乙個是數列有序,另乙個是數列使用順序儲存結構(比如陣列)。nono
二分查詢的原理及實現
二分查詢的實現原理非常簡單,首先要有乙個有序的列表。但是如果沒有,則該怎麼辦?可以使用排序演算法進行排序。
以公升序數列為例,比較乙個元素與數列中的中間位置的元素的大小,如果比中間位置的元素大,則繼續在後半部分的數列中進行二分查詢;如果比中間位置的元素小,則在數列的前半部分進行比較;如果相等,則找到了元素的位置。每次比較的數列長度都會是之前數列的一半,直到找到相等元素的位置或者最終沒有找到要找的元素。
我們先來想象一下,如果數列中有 3 個數,則先與第 2 個數進行比較,如果比第 2 個數大,則與第 2 個數右邊的數列進行二分查詢,這時這個數列就剩下乙個數了,直接比較是否相等即可。所以在 3 個數的時候最多比較兩次。
同理,在有 4 個數的時候,我們與中間數進行比較,一般中間數是首加末除以 2 算出來的,這時我們算出來的中間數是 (1+4)/2 等於 2,所以我們把要查詢的數與第 2 個數比較,若比第 2 個數小,則直接與第 1 個數比較;否則與後面兩個數進行二分查詢,這時的中間數是 (3+4)/2 等於 3,也就是後半部分的第 1 個數。再接著進行比較,相等則找到相應的元素,小於則沒有這個數(因為左邊所有的數都已經判斷過了),大於則繼續向右查詢。所以在 4 個數的時候最多比較 3 次。
以此類推,在 5 個數的時候最多查詢 3 次,在 6 個數的時候也是最多查詢 3 次。
下面我們以乙個實際的例子來看看二分查詢的操作過程。假設待查詢數列為 1、3、5、7、9、11、19,我們要找的元素為 18,下面進行二分查詢。首先我們找到中間的元素 7( (1+7)/2=4,第 4 個位置上的元素),我們要找的元素比 7 大,於是在後半部分查詢,現在後半部分數列為 9、11、19,我們找到中間元素,中間元素為 11,18與 11 比較,比 11 大,則繼續在後半部分查詢,後半部分只有乙個元素 19 了,這時直接與 19 比較,若不相等,則說明在數列中沒有找到元素,結束查詢。
對於這 7 個元素的數列,我們只查詢並比較了 3 次,是不是比較次數很少呢?
#include
using namespace std;
#define maxsize 50005
intbinarysearch
(int m)
;int a[maxsize]
;int b[maxsize]
;int m;
intmain()
cin >> n;
for(j =
0; j < n; j++
)for
(i =
0; i < n; i++
)return0;
}int
binarysearch
(int num)
else
if(num < a[middle]
)else
} cout <<
"no"
<< endl;
return0;
}
描述需對容量為c 的揹包進行裝載。從n 個物品中選取裝入揹包的物品,每件物品i 的重量為wi ,價值為pi 。對於可行的揹包裝載,揹包中物品的總重量不能超過揹包的容量,最佳裝載是指所裝入的物品價值最高。輸入
多個測例,每個測例的輸入佔三行。第一行兩個整數:n(n<=10)和c,第二行n個整數分別是w1到wn,第三行n個整數分別是p1到pn。輸出n 和 c 都等於零標誌輸入結束。
每個測例的輸出佔一行,輸出乙個整數,即最佳裝載的總價值。輸入樣例
1 211輸出樣例2 32 2
3 40 0
1【整體思路】
01揹包屬於找最優解問題,用回溯法需要構造解的子集樹。對於每乙個物品i,對於該物品只有選與不選2個決策,總共有n個物品,可以順序依次考慮每個物品,這樣就形成了一棵解空間樹: 基本思想就是遍歷這棵樹,以列舉所有情況,最後進行判斷,如果重量不超過揹包容量,且價值最大的話,該方案就是最後的答案。
在搜尋狀態空間樹時,只要左子節點是可乙個可行結點,搜尋就進入其左子樹。對於右子樹時,先計算上界函式,以判斷是否將其減去(剪枝)。
上界函式bound():當前價值cw+剩餘容量可容納的最大價值<=當前最優價值bestp。
為了更好地計算和運用上界函式剪枝,選擇先將物品按照其單位重量價值從大到小排序,此後就按照順序考慮各個物品。
【舉例說明】
對於n=4的0/1揹包問題,其解空間樹如圖所示,樹中的16個葉子結點分別代表該問題的16個可能解。
【演算法設計】
利用回溯法試設計乙個演算法求出0-1揹包問題的解,也就是求出乙個解向量xi (即對n個物品放或不放的一種的方案)
其中, (xi = 0 或1,xi = 0表示物體i不放入揹包,xi =1表示把物體i放入揹包)。
在遞迴函式backtrack中,
【時間複雜度&&優化】
因為物品只有選與不選2個決策,而總共有n個物品,所以時間複雜度為o(2n)。
因為遞迴棧最多達到n層,而且儲存所有物品的資訊也只需要常數個一維陣列,所以最終的空間複雜度為o(n)。
描述#include
int cur_weight, cur_value;
int max_value;
int c, n, time;
//time記錄求最大解的次數
int w[
100]
, v[
100]
, value[
100]
;void try (
int k )
else}}
intmain()
try (1)
; value[time++
]= max_value;}}
for( i =
1; i < time; i++
) printf (
"%d\n"
, value[i]);
return0;
}
把1到20這重新排列,使得排列後的序列a滿足:輸入a. 任意相鄰兩個數之和是素數
b. 不存在滿足條件a的序列b使得:a和b的前k(0 <= k <= 19)項相同且b的第k+1項比a的第k+1項小。(即按字典序排列的第一項)
沒有輸入。輸出輸出a,兩個數字之間用乙個空格隔開,第乙個數字前面和最後乙個數字後面沒有空格。#include
#include
#include
#include
using namespace std;
int a[21]
,book[21]
;bool isprime
(int n)
}return true;
}bool judge
(int m)
else
else
}else
//還未到第20個數字,還未成環
}else}}
void
print()
cout<
<
}bool dfs
(int n)
else
} book[i]=0
; a[n]=0
;}}return false;}}
intmain()
NOJ1130 演算法實驗三 polygon
時限 1000ms 記憶體限制 10000k 總時限 3000ms 描述在乙個周長為10000的圓上等距分布著n個點,即這n個點是乙個正n邊形的頂點。現在要另加m個點到圓上,新加的m個點可以任意選擇位置 可以與原有的點重合 然後將這n m個點中的一些點延圓周移動,最終使n m個點均勻分布,即在乙個正...
NOJ1043 演算法實驗三 跳馬
描述 在西洋棋中,馬的走法與中國象棋類似,即俗話說的 馬走日 下圖所示即西洋棋中馬 k 在一步能到達的格仔 其中黑色的格仔是能到達的位置 現有一200 200大小的西洋棋棋盤,棋盤中僅有乙個馬,給定馬的當前位置 s 和目標位置 t 求出馬最少需要多少跳才能從當前位置到達目標位置。輸入 本題包含多個測...
NOJ1149 演算法實驗四 旅遊預算
時限 1000ms 記憶體限制 10000k 總時限 3000ms 描述乙個旅行社需要估算乘汽車從某城市到另一城市的最小費用,沿路有若干加油站,每個加油站收費不一定相同。旅遊預算有如下規則 若油箱的油過半,不停車加油,除非油箱中的油不可支援到下一站 每次加油時都加滿 在乙個加油站加油時,司機要花費2...