题目大意:给你n张电影门票,但一次只可以买m张,并且你最多可以看L分钟,接下来是n场电影,每一场电影a分钟,b价值,要求恰好看m场电影所得到的最大价值,要是看不到m场电影,输出0。
三个限制:
- 选电影门票的范围;
- 总共观看的时间;
- 买的票数严格为m。
因此,将第一维滚动处理,第二三维初值负无穷(因为是严格为m),倒序递推,最后取DP[m]中的最大值即可。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_OBJ = 110, MAX_V = 100010, MAX_CNT = MAX_OBJ; //DP(obj, v, cnt)=max{DP(obj-1, v, cnt), DP(obj-1, v-objV[obj], cnt-1)+objW[obj]} int DP(int totV, int totObj, int totCnt, int *objV, int *objW) { static int DP[MAX_CNT][MAX_V]; memset(DP, 0xcf, sizeof(DP)); DP[0][0] = 0; for (int obj = 1; obj <= totObj; obj++) for (int cnt = totCnt; cnt >= 1; cnt--) for (int v = totV; v >= 1; v--) if (v >= objV[obj]) DP[cnt][v] = max(DP[cnt][v], DP[cnt - 1][v - objV[obj]] + objW[obj]); int ans = 0; for (int v = 1; v <= totV; v++) ans = max(ans, DP[totCnt][v]); return ans; } int main() { #ifdef _DEBUG freopen("c:\noi\source\input.txt", "r", stdin); #endif static int objV[MAX_OBJ], objW[MAX_OBJ]; int T, totObj, objLimit, totV; scanf("%d", &T); while (T--) { memset(objV, 0, sizeof(objV)); memset(objW, 0, sizeof(objW)); scanf("%d%d%d", &totObj, &objLimit, &totV); for (int i = 1; i <= totObj; i++) scanf("%d%d", i + objV, i + objW); printf("%d ", DP(totV, totObj, objLimit, objV, objW)); } return 0; }