程式設計思維與實踐 Week3 作業

2021-10-03 15:26:12 字數 4134 閱讀 9592

b——區間選點(貪心)

c——區間覆蓋問題(貪心)

給出n個正數,從其中選出k個數,使其總和為s,問:有多少種選數方案?

input

第一行是正數t(t<=100),表示測試的組數。每一組都輸入兩行,第一行是三個整數n,k,s,第二行是n個正整數。

output

每一組輸出結果佔一行,為方案的數目。

sample input

1

10 3 10

1 2 3 4 5 6 7 8 9 10

sample output

4
dfs,每組將輸入的n個數存在a陣列中,選擇的數存放在pick陣列中,利用solve函式,從a中第0位起,將下一位分兩種情況:不加入已選陣列,加入的已選陣列中,再進入下一位的solve函式中,進行遞迴,直到第n位。其中進行了可行性剪枝,對已選數多於k個以及已選數的和大於s的情況進行返回。當選擇的k個數總和為s時,方案數增加,及時返回。

可行性剪枝可以省下部分遞迴操作,節省了時間。還要注意每組操作之前需要清空a陣列,以及對方案數目重置0。

#

include

#include

#include

using

namespace std;

int t,count,n,k,s,m;

list<

int> pick;

vector<

int> a;

void

solve

(int i,

int sum,list<

int>

&pick)

if(i>=n || pick.

size()

>k ||sum<0)

return

;//超過選數邊界n 或 已選數多於k個 或 已選數和大於sum,則返回

solve

(i+1

,sum,pick)

;//不選第i+1個數

pick.

push_back

(a[i]);

//將第i+1個數加入已選數中

solve

(i+1

,sum-a[i]

,pick)

;//選第i+1個數

pick.

pop_back()

;}intmain()

solve(0

,s,pick)

; cout<}return0;

}

數軸上有 n 個閉區間 [a_i, b_i]。取盡量少的點,使得每個區間內都至少有乙個點(不同區間內含的點可以是同乙個)

input

第一行1個整數n(n<=100)

第2~n+1行,每行兩個整數a,b(a,b<=100)

output

乙個整數,代表選點的數目

sample input1

2

1 54 6

sample output1

1
sample input2

3

1 32 5

4 6

sample output2

2
貪心,要想盡量選取少的點使每個區間都至少乙個點,這個點一定處在這個區間與盡可能多的其他區間交叉重合的段。

將所有區間用結構體line陣列儲存,包含左端點和右端點的值。定義cmp排序標準,將所有區間的右端點按照從小到大排序,若右端點相同,則按左端點從大到小排序(盡快找到與之前區間未交叉重合的區間:小區間被交叉的話,包含他的大區間也必然被交叉,小區間應該優先排列),排序所有區間。接下來,只要選擇區間的右端點即可。

先將第乙個區間的右端點設為用於對比的邊界p,第乙個邊界先有乙個點標記,區間陣列的區間依次看,如果左端點比p大,則表示該區間與前面的區間是分離的、未交叉,需要用乙個新的點標記,p也需要更新到該區間的右端點。這樣一直到所有區間都對比完。

#

include

#include

using

namespace std;

int pointnum=0;

int n,a,b;

struct

line

;bool

compare

(line &x,line &y)

intmain()

sort

(l,l+n,compare)

;int p=l[0]

.right;

//開始的右邊界選第乙個區間的右端點

pointnum++

;//一開始用乙個點標記第乙個區間

for(

int j=

1;jcout

}

數軸上有 n (1<=n<=25000)個閉區間 [ai, bi],選擇盡量少的區間覆蓋一條指定線段 [1, t]( 1<=t<=1,000,000)。

覆蓋整點,即(1,2)+(3,4)可以覆蓋(1,4)。

不可能辦到輸出-1

input

第一行:n和t

第二行至n+1行: 每一行乙個閉區間。

output

選擇的區間的數目,不可能辦到輸出-1

sample input

3 10

1 73 6

6 10

sample output

2
貪心,要選中盡量少的區間覆蓋1~t這段線段,就要選擇能夠連續接壤且範圍最廣的區間。

仍然是把區間儲存在line結構體中,有左、右端點值。對所有區間按照左端點由小到大排序。設定乙個標誌flag(初始為true,記錄是否能連續接壤,不能置為false),乙個cur變數(記錄每一次用來對比的起點,初始為1),end變數(記錄上乙個被選擇的區間的右端點,初始為0)。

在end未到達線段終點t時,一直重複乙個工作,尋找與起點cur接壤的最大區間,從第乙個區間起開始遍歷,若接壤且未被包含,則選擇該區間,其右端點作為end的新值,直到區間都被比較完,則最後的end值就是接壤且範圍最大的區間。區間被比較完後,判斷是否選擇了新的區間作為end,如果沒有選擇新的,則說明無法連續覆蓋該線段,直接退出迴圈輸出-1,將標誌設為false。若選擇了新的區間,則區間選擇數增加,將cur設定在end的右乙個位置,作為新起點。

這道題很容易因為線段是否被完整覆蓋的錯誤判斷而wa,將起點cur設定成end+1,更好的進行比較判斷,不用對區間端點是否重合再進行多情況討論。

#

include

#include

#include

using

namespace std;

struct

line};

bool

cmp(line &x,line &y)

intmain()

sort

(vl.

begin()

,vl.

end(

),cmp)

; num=0;

len=0;

int cur=1;

//每一次劃分的起點,初始為1

int end=0;

//上一段區間的右端點,初始為0

j=0;while

(end//線段被完整覆蓋時退出迴圈}if

(cur>end)

//若未找到連續覆蓋線段的區間,則說明斷開連線

num++

; cur=end+1;

//}if(flag)//能夠完整覆蓋線段時輸出區間個數

cout

}

程式設計思維與實踐 Week3 作業

給定n個正數,從中選出k個數,令其和為s,求選數的方案數。對於每乙個數選擇與不選擇都進行dfs 邊界條件 選中k個數且和為s 選中數的個數大於k 選中數的和大於s 要選的數越界了 include using namespace std int ans 0 int a 2000 int n,k,s v...

程式設計思維與實踐 week3

題目 題意 給定n個正整數,要求選出k個數,使選出來的k個數和為sum,共有多少個方案?輸入 第一行乙個數t t 100 表示有t組測試資料。接下來的兩行,一行有三個數n,k,s,一行有n個正整數。輸出 每組資料輸出乙個和為s的方案個數,每組佔一行。思路 dfs 可行性剪枝 子集列舉問題。列舉所有子...

程式設計思維與實踐 Week3 作業 B區間選點

題意 數軸上有n個閉區間,在數軸上選取盡量少的點,使得每個區間上都有乙個點,其中乙個點可以覆蓋多個區間。思路 將各個點用結構體記錄下來,分別記錄下左右邊界。不妨設左端點為a,右端點為b。對這些點進行排序,然後將區間按b 從小到大排序 b 相同時a 從大到小排序 然後從前往後進行選點,點為選擇前乙個區...