非单位时间任务安排问题
1 #include <iostream> 2 #include<string> 3 #include<string.h> 4 using namespace std; 5 6 int main() 7 { 8 int n; 9 cin>>n; 10 int s[n]; 11 int j[n]; 12 int c[n]; 13 for(int i=0;i<n;i++) 14 { 15 cin>>s[i]>>j[i]>>c[i]; 16 } 17 int temp=0; 18 for(int i=0;i<n;i++) 19 { 20 if(temp<j[i]) 21 temp=j[i]; 22 } 23 int a[temp+1]; 24 memset(a,0,sizeof(a)); 25 int y=0; 26 for(int i=1;i<=temp;i++) 27 { 28 for(int h=0;h<n;h++) 29 { 30 if(s[h]<=i&&j[h]>=i) 31 { 32 if(a[i]>=-c[h]+a[i-s[h]]) 33 { 34 a[i]=-c[h]+a[i-s[h]]; 35 y=h; 36 } 37 } 38 } 39 j[y]=-1; 40 } 41 cout<<a[temp]; 42 return 0; 43 }
这个代码之所以不对就在于:
动态规划算法是拿起一个东西放进子问题的最优解,但它不是最后的最优解。很有可能在后面的某一个解中把它拿出来,不好控制可以被选择的物品。
它和动态规划的最大不同就是不能自如的控制可以被选择的物品,一旦曾经被选择他就再也不能被选择。
通过自己的这个算法:
我发现
动态规划和贪心算法的不同之处就在于
贪心算法一拿到就不会放,而动态规划要放进去的。
我的预想是这种
0 | 1 | 2 | 3 | 4 | 5 | 6 |
0 | -70 | -120 | -160 | -180 | -200 | -240 |
但结果是这种
0 | 1 | 2 | 3 | 4 | 5 | 6 |
0 | -70 | -120 | -160 | -180 | -200 | -200 |
结果为-200 是因为在5 的时候就拿了3 6 80,一旦被拿这个物品就不能被放回了
于是在6的时候只能和5一样
这种算法不适用于只能拿1次的情况(有限次数更麻烦,其实也可以等同于有限次数个拿一次的情况)
1 #include <iostream> 2 #include<algorithm> 3 using namespace std; 4 5 struct thread 6 { 7 int s; 8 int j; 9 int c; 10 }; 11 bool compare(thread a,thread b) 12 { 13 if(a.j<b.j) 14 return true; 15 else return false; 16 } 17 int main() 18 { 19 int n; 20 cin>>n; 21 thread m[n]; 22 for(int i=0;i<n;i++) 23 { 24 cin>>m[i].s>>m[i].j>>m[i].c; 25 } 26 int temp=0; 27 for(int i=0;i<n;i++) 28 { 29 if(temp<m[i].j) 30 temp=m[i].j; 31 } 32 sort(m,m+n,compare); 33 int a[n][temp+1]; 34 for(int i=0;i<=temp;i++) 35 { 36 if(i>=m[0].s) 37 a[0][i]=0; 38 else a[0][i]=m[0].c; 39 } 40 for(int i=1;i<n;i++) 41 { 42 for(int h=0;h<=temp;h++) 43 { 44 a[i][h]=a[i-1][h]+m[i].c; 45 if(h>m[i].j) 46 a[i][h]=a[i][m[i].j]; 47 else if(h>=m[i].s&&h<=m[i].j) 48 { 49 a[i][h]=a[i][h]>a[i-1][h-m[i].s]?a[i-1][h-m[i].s]:a[i][h]; 50 } 51 } 52 } 53 cout<<a[n-1][temp]; 54 return 0; 55 }
当只能拿一次的时候,就只能这个样子算
它想象成n*t个子问题
分别是在只有一个进程时,从零到六的每个子问题求一遍
在两个进程时,从零到六每个子问题求一遍
在n个进程时,从零到六每个子问题求一遍
首先根据它的截止时间,非减排列
进程/时间 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
0 | 30 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 90 | 60 | 30 | 30 | 30 | 30 | 30 |
2 | 130 | 90 | 60 | 30 | 30 | 30 | 30 |
3 | 200 | 130 | 90 | 60 | 30 | 30 | 30 |
4 | 250 | 180 | 130 | 90 | 60 | 60 | 60 |
5 | 270 | 200 | 150 | 110 | 80 | 80 | 80 |
6 | 350 | 280 | 230 | 190 | 160 | 150 | 110 |
在当前几个进程只需考虑新加进的进程
如果做 就是a[i-1][h-m[i].s]如果不做就是a[i-1][h]+m[i].c
当时间大于截止时间时,其a[i][h]=a[i][m[i].j];