关闭

最大工作量问题新的解法(不会证明)

标签: 算法学习动态规划数学破解
590人阅读 评论(0) 收藏 举报
分类:

上次说到的那个问题,是用暴力破解,但是我电脑跑到30位的时候就跑不动了,现在我想出一种新的算法,经过验证是对的,但是我无法证明这种算法的正确性,请数学大神帮我证明无比感谢,我再重新描述一下问题:

         小明的导师给小明分配任务,每天都有不为0的任务量,如20,40,10,20,但是小明有心脏有问题,最多连续工作两天就必须休息一天,这让小明的导师很头疼,请问如果给定任务列表,小明怎么安排才能做最多的工作,求小明最多干多少活。

我的思路是这样的:每一天只有两种状态,一种是工作,一种是休息,我们就取到当天为止最大的工作量,所以要记录小明已经连续工作的天数,如果小明已经连续工作零天,那么当天必须工作才能获取的最大值,(我们把工作的顺序记录下来1表示工作,0表示休息,最终以便求和);如果小明已经工作一天那么,就让小明今天也工作才能达到最大值;如果说小明已经连续工作了两天,那我们先把今天休息,然后算出最大工作量然后记录下来,然后如果今天选择工作的话,那么就必须昨天休息,或者是前天休息,才能让今天继续工作,所以分别把昨天休息,和前天休息的最大工作量算出来,然后比较这三种工作量,取最大的工作量,然后把对应最大工作量的顺序记录下来。然后再进行下一天的决策。

        注意上面是我递推的思路,即(d代表工作天数,max代表当前最大工作量,work代表当天的工作量)

        if d<=1

        max=max+    work;

        else

        max=max{  3中决策的最大工作量 };


需要注意的是,每次要决策完后一定要把决策的工作序列记录下来,以便后面调用,如  1101等等,这个算法可以说是一种动态规划算法,也可以说是一种贪心算法,现在就是没有证明这种算法的正确性,请大神证明:我的实现如下(java)


public class Main3 {


static class Node{
boolean[] all=null;
int index=0;
int days=0;

public Node(int length){
all=new boolean[length];
}

public int sum(int[] workList){
int sum=0;
for(int i=0;i<index;i++){
if(all[i]){
  sum+=workList[i];
}
}
return sum;
}

public static Node max(Node a,Node b,int[] workList){
return a.sum(workList)>b.sum(workList)?a:b;
}

public static Node max(Node a,Node b,Node c,int[] workList){
Node temp=max(a,b,workList);
return max(temp,c,workList);
}

public void copy(Node node){
for(int i=0;i<index;i++){
node.all[i]=all[i];
node.index=index;
node.days=days;
}
}
}

public static int getMax(int[] workList){
if(workList.length<=2){
int sum=0;
for(Integer temp:workList){
sum+=temp;
}
return sum;
}else{
Node pre=new Node(workList.length);
pre.all[0]=true;
pre.all[1]=true;
pre.index=2;
pre.days=2;
Node now=null;
for(int i=2;i<workList.length;i++){

if(pre.days==2){
//这一天休息创建一个Node
Node a=new Node(workList.length);
pre.copy(a);
a.days=0;
a.all[a.index]=false;
a.index++;
//这一天上班,但是让昨天不上班
Node b=new Node(workList.length);
pre.copy(b);
   b.days=1;
   b.all[b.index]=true;
   b.all[b.index-1]=false;
   b.index++;
   //这一天上班,但是让前天天不上班
   Node c=new Node(workList.length);
   pre.copy(c);
   c.all[c.index]=true;
   c.all[c.index-2]=false;
c.index++;
//选取最大值
now=Node.max(a, b, c, workList);
}else{
//如果这已经工作天数不是2,那么今天工作肯定达到目前最大值
Node d=new Node(workList.length);
pre.copy(d);
d.days=pre.days+1;
d.all[d.index]=true;
d.index=pre.index+1;
now=d;
}
pre=now;
}
return now.sum(workList);
}
}

public static void main(String[] args) {
int[] workList=new int[]{2000,10,2000,2000};
System.out.println(getMax(workList));
}
}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:21351次
    • 积分:418
    • 等级:
    • 排名:千里之外
    • 原创:21篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条
    文章分类
    最新评论