acm_30

来源:互联网 发布:少年维特之烦恼知乎 编辑:程序博客网 时间:2024/06/15 16:34

Gone Fishing

时间限制:3000 ms  内存限制:65535KB
难度:5
描述
John is going on a fishing trip. He has h hours available (1<= h <= 16), and there are n lakes in the area (2 <= n<= 25) all reachable along a single, one-way road. John startsat lake 1, but he can finish at any lake he wants. He can onlytravel from one lake to the next one, but he does not have to stopat any lake unless he wishes to. For each i = 1,...,n - 1, thenumber of 5-minute intervals it takes to travel from lake i to lakei + 1 is denoted ti (0 < ti <=192). For example, t3 = 4 meansthat it takes 20 minutes to travel from lake 3 to lake 4. To helpplan his fishing trip, John has gathered some information about thelakes. For each lake i, the number of fish expected to be caught inthe initial 5 minutes, denoted fi( fi >= 0 ), is known. Each 5minutes of fishing decreases the number of fish expected to becaught in the next 5-minute interval by a constant rate of di (di>= 0). If the number of fish expected to be caught in aninterval is less than or equal to di , there will be no more fishleft in the lake in the next interval. To simplify the planning,John assumes that no one else will be fishing at the lakes toaffect the number of fish he expects to catch.
Write a program to help John plan his fishing trip to maximize thenumber of fish expected to be caught. The number of minutes spentat each lake must be a multiple of 5.
输入
You will be given a number of cases in the input. Each casestarts with a line containing n. This is followed by a linecontaining h. Next, there is a line of n integers specifying fi (1<= i <=n), then a line of n integers di (1 <=i <=n),and finally, a line of n - 1 integers ti (1 <=i <=n - 1).Input is terminated by a case in which n = 0.
输出
For each test case, print the number of minutes spent at eachlake, separated by commas, for the plan achieving the maximumnumber of fish expected to be caught (you should print the entireplan on one line even if it exceeds 80 characters). This isfollowed by a line containing the number of fish expected.
If multiple plans exist, choose the one that spends as long aspossible at lake 1, even if no fish are expected to be caught insome intervals. If there is still a tie, choose the one that spendsas long as possible at lake 2, and so on. Insert a blank linebetween cases.
样例输入
2 1 10 1 2 5 2 4 4 10 15 20 17 0 3 4 3 1 2 3 4 4 10 15 50 30 0 3 4 3 1 2 3 0 
样例输出
45, 5
 Number of fish expected: 31 

240, 0, 0, 0
 Number of fish expected: 480 

115, 10, 50, 35 
Number of fish expected: 724 
来源
East Central North A
上传者
张云聪

//我的策略是使用 链表动态增长, --  好久不用linklist   debug 很久才修正了,  顺带吐槽这个输出  有空格 不说明


package GoFishing;

import java.util.Scanner;

//acm30
public class GoFishing {

    publicstatic void main(String[] args) {
       GoFishinggoFishing = new GoFishing();
      goFishing.solution();
    }

    public voidsolution() {
       in = newScanner(System.in);
      while(getdata()){
         initial();
         handle();
         ShowResult();
         System.out.println();
       }
    }
    Scannerin;
    intsize;
    inttime;
    int[]lake;
    int[]decreaseRATE;
    int[]distance;

    //获取数据
    privateboolean getdata() {
       size =in.nextInt();
       if(size ==0){
        return  false;
       }
       time =in.nextInt() * 12; // 将小时为单位的时间转化为以5min 为单位

       lake = newint[size ];
       for (int i =0; i < size; i++) {
          lake[i] =in.nextInt();
       }

       decreaseRATE= new int[size];

       for (int i =0; i < size; i++) {
         decreaseRATE[i] = in.nextInt();
       }

       distance =new int[size - 1];
       for (int i =0; i < size - 1; i++) {
          distance[i]= in.nextInt();
       }
       returntrue;
    }

    //处理数据
    private voidhandle() {
       for(int i =0 ; i < size ;i++){
         add(i+1);
       }
    }
  
    privatevoid  initial(){
       time_mark=0;
       fish_output= 0;
       link_counter= 0;
       input_head =input_tail = null;
      backup_head=backup_tail = null;
       result_head= result_tail =null;
    }
//    privatevoid printLink(){
//      Lake_Current_state  temp = result_head;
//       int count =1;
//       while(temp!= null){
//         System.out.println(count++ +": "+temp.output+"||"+temp.id);
//          temp =temp.next;
//       }
//      System.out.println("counter"+link_counter);
//      System.out.println("time"+time_mark);
//      System.out.println("==========================");
//    }
   
    private voidShowResult() {
       int[]timeSpendOnEachLake;
      timeSpendOnEachLake = new int[size];
      result_current = result_head;
       while(result_current != null) {
         timeSpendOnEachLake[result_current.id - 1]++;
         result_current = result_current.next;
       }

       for (int i =0; i < size; i++) {
          if (i != 0){
            System.out.print(", ");
            System.out.print(timeSpendOnEachLake[i] * 5);
          } else{
            System.out
                  .print((timeSpendOnEachLake[i] + time - time_mark) * 5);
          }
       }
      System.out.println();
      System.out.println("Number of fish expected: " +fish_output);
    }

    private inttime_mark = 0;
    private intfish_output = 0;
    private intlink_counter = 0;
    privateLake_Current_state input_head;
    privateLake_Current_state input_tail;

    privateLake_Current_state backup_head;
    privateLake_Current_state backup_tail;

    privateLake_Current_state result_head;
    privateLake_Current_state result_tail;
    privateLake_Current_state result_current;

    //实现链表的增长
    private voidadd(int id) {
       //output<=0 则不考虑
       if (lake[id- 1]<= 0) {
         return;
       }
       //对第一个湖的数据进行处理,由于特殊性 单独处理;
       if (id == 1){
          while(time_mark < time && lake[id -1]  >0) {
            insert_into_result(lake[id -1],id);
            time_mark++;
          }
         return;
       }
       //对于剩下的湖进行类似的处理
       // 满足两种情况 1之前的湖鱼全部钓玩 剩下的时间还是够去接下的湖钓鱼 那么就直接加,
       // 1°当前湖钓完了是时间还多 那么不做处理
       // 2°当前湖钓到一半时间用完,那么查看是否存在将花在之前湖上的时间用在这个湖上能增加效率 能则替换掉,否则不做操作
       // 2在之前的湖鱼全部钓完 剩下时间不够去接下的湖 ,那么存在一个选择问题
       //如果去那个湖钓鱼能增长的收益能抵消或者大于为了去钓鱼而放弃钓鱼的时间带来的消耗 那么去
       //attention:要考虑的不止是自己,同时也有之前未钓过鱼的湖

       int temp =0;
       intunfished_mark=25;
       for (int i =0; i <= (id - 2); i++) {
          temp +=distance[i];
         unfished_mark = (unfished_mark > i)? i : unfished_mark;
       }
       unfished_mark +=1;
      
       if(time_mark <= (time - temp)) {
          time_mark +=temp;
         distance[id-2] =0;
          while(time_mark < time && lake[id -1] > 0) {
            insert_into_result(lake[id -1],id);
            time_mark++;
          }
           
          while(lake[id -1] > result_tail.output) {
            insert_into_result(lake[id -1],id);
            remove_result_Last();
          }
       } else{
          intwaste_size = temp + time_mark - time;
          if(waste_size >= link_counter) {
            return;
          }

          intprevious_fish_output = fish_output;

          backup_tail= backup_head = new Lake_Current_state(
               result_tail.output, result_tail.id);
         remove_result_Last();
          for (int i =1; i < waste_size; i++) {
            Lake_Current_state backup_temp = new Lake_Current_state(
                  result_tail.output, result_tail.id);
            backup_temp.previous = backup_tail;
            backup_tail.next = backup_temp;
             backup_tail= backup_temp;
            remove_result_Last();
          }

         //向result注入
          int nextid=0;
          while((nextid=getNextInput(unfished_mark, id,result_tail.output))> 0){
            Lake_Current_state input_temp = new Lake_Current_state(
                  lake[nextid-1], nextid);
            insert_into_result(lake[nextid-1], nextid);
             if(input_head == null) {
                input_tail =input_head = input_temp;
             } else{
               input_temp.previous = input_tail;
               input_tail.next = input_temp;
                input_tail =input_temp;
             }

            Lake_Current_state backup_temp = new Lake_Current_state(
                  result_tail.output, result_tail.id);
            backup_temp.previous = backup_tail;
            backup_tail.next = backup_temp;
             backup_tail= backup_temp;
            remove_result_Last();
          }

          if(previous_fish_output < fish_output) {
             input_head =input_tail = null;
             backup_head= backup_tail = null;

             time_mark =time;
             for (int i =0; i <= (id - 2); i++) {
                distance[i]= 0;
             }
          } else{
            backup();
          }
       }
      
//      printLink();
    }

   //在开始和结束湖之间找到产量大于value 的湖的ID
    private intgetNextInput(int unfish_start,int end ,int value){
       int reval=-1;
       int mark=0;
       for(int i =unfish_start; i <= end;i++){
          if(lake[i-1]> value){
             if(lake[i-1]>mark){
                mark =lake[i-1];
                reval =i;
             }
          }
       }
       returnreval;
    }
    //用于向result链表中插入一个节点 按照 output降序 (由于程序是从id升序执行的 所以链表也满足按照ID升序)
    private voidinsert_into_result(final int output, final int id) {
       lake[id-1]-= decreaseRATE[id-1];
       fish_output+= output;
      link_counter++;
      result_current = result_head;
      Lake_Current_state temp = new Lake_Current_state(output, id);
       if(result_current == null) {
          result_head= result_tail = temp;
         return;
       }

       while(result_current != null) {
          if(result_current.output < output) {
               
            temp.previous = result_current.previous;
             temp.next =result_current;
             if(result_current.previous == null) {
                result_head= temp;
             }else{
               result_current.previous.next =temp;
             }
            result_current.previous = temp;
            return;
          }
         result_current = result_current.next;
       }

      result_tail.next = temp;
      temp.previous = result_tail;
       result_tail= temp;
    }

    //从result链表中删除节点
    private voiddelete_from_result(int output, int id) {
       lake[id-1]+= decreaseRATE[id-1];
       fish_output-= output;
      link_counter--;
      result_current = result_head;
       while(result_current != null) {
          if(result_current.output == output && result_current.id ==id) {
             if(result_current.previous == null) {
                if(result_head == result_tail) {
                   result_tail= result_head = result_current = null;
                  return;
                }

                result_head= result_head.next;
               result_head.previous = result_current = null;
               return;
             }

             if(result_current.next == null) {
                result_tail= result_tail.previous;
               result_tail.next = result_current = null;
               return;
             }

            result_current.previous.next = result_current.next;
            result_current.next.previous = result_current.previous;
            result_current = null;
            return;
          }
         result_current = result_current.next;
       }
    }

    //移除result链表最后一项
    private voidremove_result_Last() {
      lake[result_tail.id-1] += decreaseRATE[result_tail.id-1];
       fish_output-= result_tail.output;
      link_counter--;
       if(result_tail == null) {
         return;
       }

       if(result_head == result_tail) {
          result_head= result_tail = null;
       } else{
          result_tail= result_tail.previous;
         result_tail.next = null;
       }
    }

    //用于result链表的复原
    private voidbackup() {
      Lake_Current_state temp = backup_head;
       while (temp!= null) {
         insert_into_result(temp.output, temp.id);
          temp =temp.next;
       }
       temp =input_head;
       while (temp!= null) {
         delete_from_result(temp.output, temp.id);
          temp =temp.next;
       }
       input_head =input_tail = null;
       backup_head= backup_tail = null;
    }

    // 记录湖的状态同时也是链表节点
    classLake_Current_state {

       int output =-1; // 湖当前产鱼量
       int id =-1;// 湖的编号

      Lake_Current_state previous = null;
      Lake_Current_state next = null;

       publicLake_Current_state(int output, int id) {
          this.output= output;
          this.id =id;
       }
    }

}


0 0
原创粉丝点击