寫在前面:
這次實驗的後兩個題均選擇貪心求解,而這是一篇對貪心演算法講的比較詳細的部落格,寫在前面以便之後瀏覽。
題目:
給定n個正數,其中選取k 個數使他們的和為s,怎樣選?
input:
t組數,其中t<=100;對於每一種情況,都有兩行,第一行為資料量n,要選取k 個數,和為s,第二行,n個正數。
output:
對於每種情況,輸出乙個整數表示可行解的個數 。
思路:
基本思路就是可以列舉,和求子集的列舉方法類似。
在乙個組合內,每乙個數都是加入或者不加入兩種選擇。
fun
(i+1
,sum,res)
;//不選
res.
push_back
(a[i]);
//選fun
(i+1
,sum-a[i]
,res)
;res.
pop_back()
;
每一次都是不選或者選兩種情況,如果不選的話,就直接i+1,sum 不變;
如果選的話,就是將當前元素加入到列表t 種,同時需要注意的是,在下面要有乙個pop_back,以便將最後乙個元素刪除,得到更多的組合。
需要注意的是終點的判斷:
滿足情況的是:res.size()==k && sum==0
需要提前終止的是:res.size()> k||sum<0
越界的是:i>=n
**:
//選數問題 k<=n<=16 n個數,k個元素,總和是sum
#include
#include
#include
using
namespace std;
int k,n,tol=0;
int a[20]
;void
fun(
int i,
int sum,list<
int>
&res)
coutif(i>=n)
return;if
(res.
size()
> k||sum<0)
return
;fun
(i+1
,sum,res)
;//不選
res.
push_back
(a[i]);
//選fun
(i+1
,sum-a[i]
,res)
; res.
pop_back()
;}intmain()
}
題目:
數軸上有 n 個閉區間 [a_i, b_i]。取盡量少的點,使得每個區間內都至少有乙個點(不同區間內含的點可以是同乙個)
input:
第一行1個整數n(n<=100)
第2~n+1行,每行兩個整數a,b(a,b<=100)
output:
乙個整數,代表選點的數目
思路:
這個題目是在區間內選擇盡量少的點,考慮用貪心求解,主要問題仍然是貪心準則,選最少的點覆蓋所有區間。首先能想到的是假如存在區間[a,b],那麼對任何的區間[c,d] (cbool
compare
(section s,section e)
而當s[i].x>now.y
則表示需要選擇新的點了,此時count++;
這樣的得出來的結果就是最優解。
**:
//區間選點問題
#include
#include
#include
#include
using
namespace std;
struct section};
void
fun(section *s,
int n)
} cout<}int
main()
sort
(s,s+n)
;fun
(s,n)
;}
題目:
數軸上有 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
思路:
這個首先要思考的問題就是怎麼選取區間,這就容易使人想到貪心準則,對當前的每一步都選取能獲得最大利益的。
據此得到的貪心準則如下:
假設當前選取的區間是[a,b]那麼選取下一段的準則就是能覆蓋到b點,且右端點最大的區間。
這就相當於解決了選點的中間過程,接下來要解決的就是起點和終點問題。
容易得到,第乙個區間就是包含給定區間左端點且右端點最大的區間,
而終點就是所選區間已經包含給定區間的右端點,一旦達到,即刻終止。
總結:
針對這種怎樣取得最值的問題,要保持用貪心演算法的求解的警惕性。而貪心演算法最重要的就是貪心準則,在實驗中發現起點和終止條件也很重要。
在實驗中獲得的另乙個教訓是是想問題要全面,注意一旦明確可以或者不可以的情況,要及時終止,這裡講一點細節問題。比如假設找到的第乙個區間就已經可以覆蓋所有區間的情況就可以實現,能終止。要考慮中間過程中的情況,當下乙個區間的左端點都比尋找的區間右端點大的時候就肯定無法實現,可以終止。同時要對執行完的情況給出反饋。
再乙個教訓就是需要對輸入的資料進行排序,再進行運算,這樣能保證順序處理就是結果,如果資料是亂的,結果就會出現很大的問題。
**:
#include
#include
#include
using
namespace std;
struct section};
section s[
30000];
intfun
(section *s,
int n,
int t)
if(s[i]
.x>1)
break
; i++
;//break;}if
(!flag)
return-1
; flag=
false;
count++
;//第乙個元素
if(now.y>=t)
return count;
for(
;i(next.y>=t)
return count+1;
flag=
true
; i++;}
now=next;
count++;if
(!flag)
return-1
; flag=
false;}
if(now.y < t)
return-1
;return count;
}int
main()
sort
(s,s+n)
;int count=
fun(s,n,t)
;printf
("%d\n"
,count);}
}
Week3 作業A 選數 dfs剪枝
有n個數,從中選取k個,要求和為s,計算有多少種選數的方法。其中,k n 16。dfs遞迴求解,n個數存放在陣列a內,遞迴函式的引數為sum i,表示從a i 向後選數,和為sum,選出的數放進全域性變數vector容器v內。當v中元素數為k並且sum 0時,找到一種符合條件的選數方法 當i n或者...
作業3 閱讀與提問
閱讀 構建之法 第1 5章 一 第一章 概論 it人基本職業道德是什麼?有時候是否跟潮流走,用大多it人的道德來規範自己,還是按照自己的心裡底線?二 第二章 個人技術和流程 如何快速提高it員個人技術,是自己單獨學習還是和別人討論試學習,和別人討論試學習時,是和自己水平差不多的還是和比自己厲害很多的...
系統設計與分析 作業3
簡述瀑布模型 增量模型 螺旋模型 含原型方法 並分析優缺點 瀑布模型 定義 是將工作分為需求 設計 實現 驗證 維護等等階段,這些階段動的工作物件來自於上一項活動的輸出,這些輸出一般是代表本階段活動結束的里程碑式的文件。每個階段根據本階段的活動規程執行相應的任務,並對本階段活動執 況進行評審。優點 ...