描述
ycb是個天資聰穎的孩子,他的夢想是成為世界上最偉大的acmer。為此,他想拜附近最有威望的dalao為師。dalao為了判斷他的資質,給他出了乙個難題。dalao把他帶到乙個到處都是題的oj裡對他說:「孩子,這個oj裡有一些不同的題,做每一道題都需要一些時間,每一題也有它自身的rp(人品值)。我會給你一段時間,在這段時間裡,你可以做一些題。如果你是乙個聰明的孩子,你應該可以讓做題的總rp最大。」 如果你是ycb,你能完成這個任務嗎?
輸入輸入檔案的第一行是乙個t,表示測試組數,接下來t組每組第一行包含兩個正整數n,m。m表示總共能夠用來做題的時間,n代表oj裡的題目的數目。接下來的n行每行包括兩個的整數,分別表示做每個題的時間ti和這道題的人品值vi。
1 <= n, m <= 100000,
1 <= ti, vi <= 10
輸出輸出檔案僅包含乙個整數表示規定時間內可以做題得到的最大人品值。
樣例輸入1
複製
13 9
10 10
8 1
1 2
樣例輸出1
3一拿到這題首先想到了01揹包,但會超時。
仔細看了資料範圍1 <= ti, vi <= 10發現其實所有題之間肯定會出現重複情況,因為做題時間與人品值的組合最多有100種,而題目最多有100000道,因此這道題其實就是多重揹包拆分後的情況。
然而普通做法(拆成乙個乙個)會超時,我們就可以考慮將相同的題目的數量拆成不同的數值,使得這些數值之間可以組合成小於等於題目數量的任意數值。
比如7可以拆成1,2,4,他們之間的任意幾個數可以組成小於等於11的任意值。
那麼怎樣能夠找到這些拆分後的數呢?利用二進位制即可。
7的二進位制為111,7可以拆成001,010,100即為1,2,4。這樣就把拆成n個問題,變為拆成logn個問題集合,dp時間複雜度得到明顯的優化。
#include#includeint f[100005],v[100005],w[100005],a[15][15
];int max(int x,int
y)int
main()
memset(f,
0,sizeof
(f));
memset(v,
0,sizeof
(v));
memset(w,
0,sizeof
(w));
c=0;
for(i=1;i<=10;i++)
if(a[i][j]>0
) }}}
for(i=1;i<=c;i++)
}printf(
"%d\n
",f[v]);
}return0;
}
acm高階之路
一般要做到50行以內的程式不用除錯 100行以內的二分鐘內除錯成功 第一階段 練經典常用演算法,下面的每個演算法給我打上十到二十遍,同時自己精簡 因為太常用,所以要練到寫時不用想,10 15分鐘內打完 1.最短路 floyd dijstra,bellmanford 2.最小生成樹 先寫個prim,k...
ACM高階指南
acm隊不是為了一場比賽而存在的,為的是隊員的整體提高。大學期間,acm隊隊員必須要學好的課程有 l c c 兩種語言 l 高等數學 l 線性代數 l 資料結構 l 離散數學 l 資料庫原理 l 作業系統原理 l 計算機組成原理 l 人工智慧 l 編譯原理 l 演算法設計與分析 除此之外,我希望你們...
Acm高階指南
acm隊不是為了一場比賽而存在的,為的是隊員的整體提高。大學期間,acm隊隊員必須要學好的課程有 l c c 兩種語言 l 高等數學 l 線性代數 l 資料結構 l 離散數學 l 資料庫原理 l 作業系統原理 l 計算機組成原理 l 人工智慧 l 編譯原理 l 演算法設計與分析 除此之外,我希望你們...