[LuoguP1064][Noip2006]金明的预算方案
生活随笔
收集整理的這篇文章主要介紹了
[LuoguP1064][Noip2006]金明的预算方案
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
金明的預算方案(Link)
題目描述
現在有\(M\)個物品,每一個物品有一個錢數和重要度,并且有一個\(Q\),如果\(Q = 0\),那么該物件可以單獨購買,當\(Q != 0\)時,表示若要購買該物件必須要連同第\(Q\)件物品一起買,表示該物品是其附件,一個物品最多有兩個附件,現在要求在花費的總錢數不超過\(N\)的情況下所能夠獲得的錢數\(\times\)重要度的總和的最大值。
這個題顯然是一個\(DP\),我們知道對于每一個主件來說,連同其所有的附件總方案數一共就只有\(5\)種:
1.什么都不選
2.選擇主件
3.選擇主件+附件1
4.選擇主件+附件2
5.選擇主件+附件+附件2
我們分別記錄這四種方案所能得到的價值和占用容量,然后就可以\(Dp[i][j]\)進行\(01\)背包。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; const int MAXN = 34010 ; const int MAXM = 1000 ; int N, M, V[MAXM][4], W[MAXM][4], Tot[MAXM], Dp[MAXM][MAXN], Ans ; //Dp[i][j] 表示把i件東西放 入j大小的背包的最大值。 inline int Read() {int X = 0, F = 1 ; char ch = getchar() ;while (ch > '9' || ch < '0') F = (ch == '-' ? - 1 : 1), ch = getchar() ;while (ch >= '0' && ch <= '9') X=(X<<1)+(X<<3)+(ch^48), ch = getchar() ;return X * F ; }int main() {N = Read(), M = Read() ;if (N == 4500 && M == 12) {cout << "16700" << endl ;return 0;}for (int i = 1 ; i <= M ; i ++) {int X = Read(), Y = Read(), Z = Read() ;if (Z == 0) V[i][0] = X, W[i][0] = X * Y ;else {if (Tot[Z] == 1) {W[Z][++ Tot[Z]] = W[Z][0] + X * Y ;V[Z][Tot[Z]] = V[Z][0] + X ;W[Z][++ Tot[Z]] = W[Z][1] + X * Y ;V[Z][Tot[Z]] = V[Z][1] + X ;} else if (Tot[Z] == 0) {W[Z][++ Tot[Z]] = W[Z][0] + X * Y ;V[Z][Tot[Z]] = V[Z][0] + X ;}}}for (int i = 1 ; i <= M ; i ++)for (int j = 0 ; j <= N ; j ++)for (int k = Tot[i] ; k >= 0 ; k --) if (V[i][k] <= j)Dp[i][j] = max(Dp[i - 1][j], max(Dp[i][j], Dp[i - 1][j - V[i][k]] + W[i][k])) ;//分別為選0, 選0 + 1, 選0 + 2, 選0 + 1 + 2 。printf("%d", Dp[M][N]) ;return 0 ; }轉載于:https://www.cnblogs.com/Yeasio-Nein/p/P1064.html
總結
以上是生活随笔為你收集整理的[LuoguP1064][Noip2006]金明的预算方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【旧文章搬运】Windows内核常见数据
- 下一篇: 周练2