zhuangzai_wenti

#include<cstdio>
  int casenum;
  int boxnum;
  int boxw[22];
  int boatload1,boatload2;
  int restw;
  int bestw=0;
  int noww;
  void dfs(int i){
      //  printf("第%d层:bestw是:%d \t noww的值:%d \t 剩下的重量restw=%d\n",i,bestw,noww,restw);
      if(i>boxnum){
        if(noww>bestw){
            bestw=noww;
        }
      }
      else{

        if(noww+boxw[i]<=boatload1&&noww+restw>bestw){//只要我还装的下,并且我如果把剩下的箱子全部都装了都不必之前的解空间中的最优解大,我就不走了!
            noww+=boxw[i];
            if(noww>bestw) bestw=noww;
             restw-=boxw[i]; //这才能减去,这在递归到下一层的时候才修正剩下的重量
         //   printf("左子树:bestw的值%d \t noww的值:%d \t 剩下的重量restw=%d\n",bestw,noww,restw);
            dfs(i+1);
         //   printf("我来过\n");
            restw+=boxw[i];//就是递归回来的时候我要重新修正我的重量值,但是因为下面的是不要第i个箱子的重量所以就不用加回去了,
            //不对,还是要加回去,因为要第i个箱子的时候,这个路是可能被剪掉的,这样就会使得剩下的重量并没有被减去
            //所以,你要自己加回去在下面第二个递归的时候才自己减去,这样才保险
            noww-=boxw[i];
        }
         restw-=boxw[i];  //无论我装还是不装,第i个箱子,剩下的重量都要减掉第i个箱子的重量
       //   printf("第%d层的中间层@@@@@@@@@@@@@:bestw是:%d \t noww的值:%d \t 剩下的重量restw=%d\n",i,bestw,noww,restw);
        if(noww+restw>bestw){//我不装这第i个箱子,如果加上剩下的都不够解空间大,就不走了
       //     printf("我来过第二条路径\n");
            dfs(i+1);
        }
        restw+=boxw[i];//最后也要重新加上,因为不加,那么这个回溯的时候就会造成restw一直这么小了
      }
      //  printf("第%d层结束----------------------------\n",i,bestw);

  }
int main (){

    scanf("%d",&casenum);
    for(int i=1;i<=casenum;++i){
        scanf("%d",&boxnum);
        scanf("%d%d",&boatload1,&boatload2);
        bestw=0;
        restw=0;
        for(int j=1;j<=boxnum;++j){
            scanf("%d",&boxw[j]);
            restw+=boxw[j];
        }
        dfs(1);
        if(boatload2<restw-bestw){
            printf("Case %d:\nNo\n",i);
        }
        else
        printf("Case %d:\n%d\n",i,bestw);
    }
}

猜你喜欢

转载自www.cnblogs.com/waibizi/p/12070210.html