洛谷 P1048 採藥 (啟發式搜尋)
阿新 • • 發佈:2020-07-21
題面
題目描述
辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了一個難題。醫師把他帶到一個到處都是草藥的山洞裡對他說:“孩子,這個山洞裡有一些不同的草藥,採每一株都需要一些時間,每一株也有它自身的價值。我會給你一段時間,在這段時間裡,你可以採到一些草藥。如果你是一個聰明的孩子,你應該可以讓採到的草藥的總價值最大。”
如果你是辰辰,你能完成這個任務嗎?
輸入格式
第一行有 22 個整數 TT(1 \le T \le 10001≤T≤1000)和 MM(1 \le M \le 1001≤M≤100),用一個空格隔開,TT 代表總共能夠用來採藥的時間,MM 代表山洞裡的草藥的數目。
接下來的 MM 行每行包括兩個在 11 到 100100 之間(包括 11 和 100100)的整數,分別表示採摘某株草藥的時間和這株草藥的價值。
輸出格式
輸出在規定的時間內可以採到的草藥的最大總價值。
程式碼實現
很明顯的揹包吧。這裡我們寫一個啟發式搜尋,所謂的啟發式搜尋,就是我們在搜尋的時候用一個估價函式去幫助和優化我們的決策。當我們選擇一樣草藥的時候沒什麼好說的,直接往下搜,當我們不選的時間,我們有估價函式來幫助我們判斷,接下來的價值是否大於我們目前的最優值,如果不大於那麼顯然我們沒有必要進行下一輪的搜尋。你可以理解為這個估價函式是幫助我們剪枝的一個工具。
程式碼實現
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<cstring> using namespace std; typedef long long ll; int n,m,ans; const int maxn=105; struct node { int a,b; double val; }e[maxn]; bool cmp (node a,node b) { return a.val>b.val; } int f(int t,int v) { int tot=0; for (int i=0;i+t<=n;i++) { if (v>=e[t+i].a) { v-=e[i+t].a; tot+=e[i+t].b; } else return (int ) (tot+v*e[i+t].val); } return tot; } void dfs (int t,int pass,int v) { ans=max (ans,v); if (t>n) return ; if (f(t,pass)+v>=ans) dfs (t+1,pass,v); if (e[t].b<pass) dfs (t+1,pass-e[t].a,v+e[t].b); } int main () { cin>>m>>n; for (int i=1;i<=n;i++) { cin>>e[i].a>>e[i].b; e[i].val=1.0*e[i].b/e[i].a; } sort (e+1,e+1+n,cmp); dfs (1,m,0); cout<<ans<<endl; return 0; }