CCh99

非单位时间任务安排问题

 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];

posted on 2019-04-16 21:18  CCh99  阅读(1047)  评论(0编辑  收藏  举报

导航