P1048 採藥 01揹包模板)

2021-10-02 09:08:35 字數 4152 閱讀 4409

題意:

給我們乙個可以採藥的時間t,接下來用m 種藥,第i種藥採摘需要用w[i]的時間,有v[i]的價值。我們需要在時間t內採摘到最大的價值。

我通過這題學習了01揹包。

無優化

#pragma gcc optimize(3,"ofast","inline")

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define f(i,s,t) for(int i=(s);i<=(t);i++)

#define d(i,s,t) for(int i=(s);i>=(t);i--)

#define dbug(i) printf("value=%d\n",i)

#define ddbug(i,j) printf("value=%d %d\n",i,j)

#define ed putchar('\n')

#define fo freopen("d:\\in.txt","r",stdin)

#define ios cin.tie(0) ,cout.tie(0), cout.sync_with_stdio(0)

typedef

long

long ll;

//const int inf = 1 << 30;

//const double eps = 1e-6;

//#define mx 102

//#define mod 10000

using

namespace std;

int t, m, dp[

102]

[1002];

//t表示有的時間,m表示藥草的數目

int time[

102]

, value[

102]

;//用於存藥草採集需要的時間和其價值

intmain()

//inner for

}//extren for

cout << dp[m]

[t]<< endl;

return0;

}

優化到一維:

一維dp的大小取決於揹包的容量。

在一維dp中,容量大的值是由容量小的值和v決定的。

所以,一維內層迴圈要倒著來!不然會重複!!!

int t, m,dp[

1002];

int w[

102]

, v[

102]

;int

main()

當然可以繼續進行常數級優化:

我們01揹包用了兩層的for迴圈,第一層列舉物體的種類數,第二層列舉揹包的容量。

對於第二層迴圈,如果當前列舉揹包容量的大小 可以 裝上 第一層迴圈列舉的物品,那麼就要呼叫狀態轉移方程:dp[j] = max(dp[j-w[i]]+v[i],dp[j]);

那麼,因為第二層迴圈列舉揹包容量的大小是遞減的,如果列舉到乙個揹包容量裝不下該物品的,那麼接下來列舉到的揹包容量也一定裝不下該物品了,接下來是列舉都是無意義的。

那麼,我們列舉揹包容量時,只需要到該物品的重量就好了!

#pragma gcc optimize(3,"ofast","inline")

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define f(i,s,t) for(int i=(s);i<=(t);i++)

#define d(i,s,t) for(int i=(s);i>=(t);i--)

#define dbug(i) printf("value=%d\n",i)

#define ddbug(i,j) printf("value=%d %d\n",i,j)

#define ed putchar('\n')

#define fo freopen("d:\\in.txt","r",stdin)

#define ios cin.tie(0) ,cout.tie(0), cout.sync_with_stdio(0)

typedef

long

long ll;

//const int inf = 1 << 30;

//const double eps = 1e-6;

//#define mx 102

//#define mod 10000

using

namespace std;

int t, m, dp[

1002];

int time[

102]

, value[

102]

;int

main()

f(i,

1, m)

//inner for

}//extren for

cout << dp[t]

<< endl;

return0;

}

前面可以得到第二層迴圈列舉揹包容量我們列舉到當前物品的重量就可以了,我們還可以進一步進行優化的。

我們新增乙個變數,sumw ,表示剩餘物品的總重量。具體如下:

#pragma gcc optimize(3,"ofast","inline")

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define f(i,s,t) for(int i=(s);i<=(t);i++)

#define d(i,s,t) for(int i=(s);i>=(t);i--)

#define dbug(i) printf("value=%d\n",i)

#define ddbug(i,j) printf("value=%d %d\n",i,j)

#define ed putchar('\n')

#define fo freopen("d:\\in.txt","r",stdin)

#define ios cin.tie(0) ,cout.tie(0), cout.sync_with_stdio(0)

typedef

long

long ll;

//const int inf = 1 << 30;

//const double eps = 1e-6;

//#define mx 102

//#define mod 10000

using

namespace std;

int t, m, dp[

1002];

int time[

102]

, value[

102]

;int

main()

//for

f(i,

1, m)

//inner for

sumw -

= time[i];}

//extren for

cout << dp[t]

<< endl;

return0;

}

洛谷 P1048 採藥 01揹包

辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了乙個難題。醫師把他帶到乙個到處都是草藥的山洞裡對他說 孩子,這個山洞裡有一些不同的草藥,採每一株都需要一些時間,每一株也有它自身的價值。我會給你一段時間,在這段時間裡,你可以採...

洛谷P1048 採藥 01揹包

辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了乙個難題。醫師把他帶到乙個到處都是草藥的山洞裡對他說 孩子,這個山洞裡有一些不同的草藥,採每一株都需要一些時間,每一株也有它自身的價值。我會給你一段時間,在這段時間裡,你可以採...

P1048 採藥 DP 01揹包

辰辰是個天資聰穎的孩子,他的夢想是成為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了乙個難題。醫師把他帶到乙個到處都是草藥的山洞裡對他說 孩子,這個山洞裡有一些不同的草藥,採每一株都需要一些時間,每一株也有它自身的價值。我會給你一段時間,在這段時間裡,你可以採...