標籤:暴力 include 答案 貪心 efi text 準備 badge color
P1233 木棍加工題目描述
一堆木頭棍子共有n根,每根棍子的長度和寬度都是已知的。棍子可以被一台機器一個接一個地加工。機器處理一根棍子之前需要準備時間。準備時間是這樣定義的:
第一根棍子的準備時間為1分鐘;
如果剛處理完長度為L,寬度為W的棍子,那麼如果下一個棍子長度為Li,寬度為Wi,並且滿足L>=Li,W>=Wi,這個棍子就不需要準備時間,否則需要1分鐘的準備時間;
計算處理完n根棍子所需要的最短準備時間。比如,你有5根棍子,長度和寬度分別為(4, 9),(5, 2),(2, 1),(3, 5),(1, 4),最短準備時間為2(按(4, 9)、(3, 5)、(1, 4)、(5, 2)、(2, 1)的次序進行加工)。
輸入輸出格式輸入格式:
第一行是一個整數n(n<=5000),第2行是2n個整數,分別是L1,W1,L2,w2,…,Ln,Wn。L和W的值均不超過10000,相鄰兩數之間用空格分開。
輸出格式:
僅一行,一個整數,所需要的最短準備時間。
輸入輸出範例輸入範例#1:
54 9 5 2 2 1 3 5 1 4
輸出範例#1:
2
拿到這道題,第一思路:暴力,用騷操作最佳化一下,說不定會快的飛起呢!!!
但實際上,只要稍微一思考,就會發現這就是一道赤裸裸的dp啊。
我們進一步分析,會發現,要同時滿足l0>l1,w0>w1,就說明它有兩種屬性,傻子都看的出這題的貪心就是使序列滿足兩種屬性的同時,儘可能多的
找出最長上升子序列,對不對?
同時又由於dilworth定理我們知道,同一個序列裡,最長上升子序列的個數就等於最長不上升子序列的長度,所以我們又把問題裝換成了求最長不上升子序列
我相信大家一定都會O(nlogn)演算法來求,對不對?
所以我在此不再贅述。
但是還有一個問題,如何處理雙重屬性的問題,我們有一個通用的方法,就是將其中的一重屬性排序,來求另一重的目標序列,這個東西啊,我講也講不清楚
自己多體會體會,再用一些騷操作,我相信你會明白的,對不對?
諾,下面是代碼(我用STL寫的)
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define maxn 5000+5using namespace std;int n,f[maxn];struct stack{ int l,w;}s[maxn];bool cmp(const stack &a,const stack &b){ return a.l>b.l;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&s[i].l,&s[i].w); sort(s+1,s+1+n,cmp);//給屬性降維 /*求最長不上升子序列*/ int len=0; for(int i=1;i<=n;i++) { if(s[i].w>f[len]) { f[++len]=s[i].w; } else{ int k=lower_bound(f+1,f+1+len,s[i].w)-f; f[k]=s[i].w; } }
printf("%d",len);
//長度即使答案。
return 0;}
我還是很蒟蒻的,所以如果有任何漏洞的話,還請讀者大老爺們指出QAQ
謝謝大家!……!
dilworth定理+屬性排序(木棍加工)