题意:
n个物品,可以在A机器上加工花费t1,可以在B机器上加工花费t2,或者A、B同时加工花费t3,
A、B同时加工物品,求加工所有的物品的最短用时
神奇的dp:
因为用背包转移状态,转移后背包是填满的状态 ,
所以我们不用排序考虑物品选择那种方式加工 ,不用担心同时加工会不会耽误空档时间,不用考虑谁先谁后的问题, 背包的优势在这道题上体现了出来
f[i][j]表示加工前i个物品A机器加工总时间为j时B的最小时间
转移方程:
f[i][j] = min(f[i][j],f[i-1][j-a[i].t1])
f[i][j] = min(f[i][j],f[i-1][j]+a[i].t2)
f[i][j] = min(f[i][j],f[i-1][j-a[i].t3]+a[i].t3)
细节:
范围为n《=6000,t 《=5,所以直接开二维数组会MLE,要用滚动数组压掉一维
在写的时候要先判断第二个状态,再判断剩余两个状态,便于转移
这样我们又会发现TLE了,考虑优化,由于t《=5,所以前i个物品最大时间就是5*i,于是j从5*i倒叙枚举,就可以解决TLE的问题
时间复杂度:O(小于n*n*5)
好题!!!
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 #define minn(x,y) x<y?x:y 6 #define maxn(x,y) x>y?x:y 7 #define re register 8 struct node 9 { 10 int t1,t2,t3; 11 }a[6005]; 12 int f[30005]; 13 inline int read() 14 { 15 int res = 0,f = 1; 16 char c; 17 c = getchar(); 18 while(c < '0' || c > '9') 19 { 20 if(c == '-')f = -1; 21 c = getchar(); 22 } 23 while(c >= '0' && c <= '9') 24 { 25 res = res * 10 + c - '0'; 26 c = getchar(); 27 } 28 return res * f; 29 } 30 int main() 31 { 32 int n,sum = 0; 33 n = read(); 34 for(re int i = 1;i <= n;i ++) 35 { 36 a[i].t1 = read(); 37 a[i].t2 = read(); 38 a[i].t3 = read(); 39 sum = sum + max(a[i].t1,a[i].t3); 40 41 } 42 for(re int i = 1;i <= sum;i ++)f[i] = 1e9; 43 for(re int i = 1;i <= n;i ++) 44 { 45 for(re int j = 5 * i;j >= 0;j --) 46 { 47 if(a[i].t2)f[j] = f[j] + a[i].t2; 48 else f[j] = 1e9; 49 if(a[i].t3 && j >= a[i].t3)f[j] = minn(f[j],f[j - a[i].t3] + a[i].t3); 50 if(a[i].t1 && j >= a[i].t1)f[j] = minn(f[j],f[j - a[i].t1]); 51 } 52 } 53 int ans = 1e9; 54 for(re int i = 0;i <= sum;i ++) 55 { 56 ans = min(ans,maxn(i,f[i])); 57 } 58 printf("%d",ans); 59 return 0; 60 }