(点击此处查看原题)
题意
简单来说,就是一个完全背包,不过这里卡住了常规的完全背包写法,时间复杂度为O( V*∑( V/c[i] ))如下所示:
for(int i = 1;i <= n ;i ++) { scanf("%d%d",cost+i,val+i); for(int j = t; j >= cost[i] ; j --) { for(int k = 1; k * cost[i] <= j ;k ++) { dp[j] = max(dp[j],dp[j-k*cost[i]] + k * val[i]); } } }
解题思路
既然普通的写法无法解决,那就采用如下的优化即可,时间复杂度为O(NV),题目满足N*T <= 1e7,因此可以跑过去:
for(int i = 1;i <= n ;i ++) { scanf("%d%d",cost+i,val+i); for(int j = cost[i]; j <= t; j ++) { dp[j] = max(dp[j],dp[j-cost[i]] + val[i]); } }
代码区
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<string> #include<fstream> #include<vector> #include<stack> #include <map> #include <iomanip> #define bug cout << "**********" << endl #define show(x, y) cout<<"["<<x<<","<<y<<"] " #define LOCAL = 1; using namespace std; typedef long long ll; const int inf = 1e9 + 7; const ll mod = 1e9 + 7; const int Max = 1e5 + 10; int t, n; int cost[Max],val[Max]; int dp[Max]; //记录价格为i的时候的最大价值 int main() { #ifdef LOCAL // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); #endif scanf("%d%d",&t,&n); memset(dp,0,sizeof(dp)); for(int i = 1;i <= n ;i ++) { scanf("%d%d",cost+i,val+i); for(int j = cost[i]; j <= t; j ++) { dp[j] = max(dp[j],dp[j-cost[i]] + val[i]); } } printf("%d ",dp[t]); return 0; }