zoukankan      html  css  js  c++  java
  • 贪心算法《过河问题》

    描述

    在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,N人所需要的时间已知;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,如何设计一个方案,让这N人尽快过桥。 

     
    输入
    第一行是一个整数T(1<=T<=20)表示测试数据的组数
    每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河
    每组测试数据的第二行是N个整数Si,表示此人过河所需要花时间。(0<Si<=100)
    输出
    输出所有人都过河需要用的最少时间
    样例输入
    1
    4
    1 2 5 10
    样例输出
    17
    分析:以1 2 5 10和1 5 7 10为例子分析大致思路
    一,1 2 5 10.(当最快两个人的速度相差不大时)
    1.  先最快的一组过河,然后将该组的最快的人回到原地传递电筒。
    2.  将走的最慢的一组过河,然后由第一组剩下的人,将电筒带回。
    3.  重复1. 2.步骤
    二,1 5 7 10(当最快两个人的速度相差较大时)
    思路。最慢和最快的人一起过河,并由最快的人带回电筒。以此重复。
    如果该组数据使用一方法。一共是23,而方法二,需要21

    总结以上:相当于把最快的一组或一个人当做小车载最慢的一组过河。当把他们慢的组都运完了(没有留下单个的人,那么一共肯定是偶数个人,否则为奇数个)
    ,再处理最快组合余下的人。
    注意:当人小于等于3时,就不需要前面的处理。

    这是WA的代码:我还不知道错在哪里。欢迎改正。再下面是正确代码,也是对该代码的优化:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    int main()
    {
     int repeat;
     cin >> repeat;
     for (int i = 0; i < repeat; i++)
     {
      int datanum;
      cin >> datanum;
      int *ps = new int[datanum];
      //输入各个人的时间
      for (int j = 0; j < datanum; j++)
      {
       cin >> ps[j];
      }
      //排序
      sort(ps, ps + datanum); //sort()默认从小到大排序

      for (int j = 0; j < datanum; j++)
      {
       cout << ps[j] << " ";
      }
      //主要算法
      //datanum的奇数偶数分为两种算法
      int MinTime1 = 0;
      int MinTime2 = 0;
      int MinTime = 0;
      cout << endl;
      if (datanum % 2 == 0&&datanum>1)
      {
       for (int j = datanum - 1; j>1; j-=2)
       {
        MinTime1 = ps[0] + ps[1] + ps[j] + ps[1];
        MinTime2 = ps[j] + ps[j - 1] + 2 * ps[0];
        if (MinTime1 < MinTime2){ MinTime += MinTime1; cout << "1"; }
        else{ MinTime += MinTime2; cout << "2" << MinTime2 << " " << MinTime1 << endl; }
       }
       MinTime += ps[1];
      }
      else if (datanum%2!=0&&datanum>1)
      {
       for (int j = datanum - 1; j>2; j -= 2)
       {
        MinTime1 = ps[0] + ps[1] + ps[j] + ps[1];
        MinTime2 = ps[j] + ps[j - 1] + 2 * ps[0];
        if (MinTime1 < MinTime2){ MinTime += MinTime1; }
        else{ MinTime += MinTime2; }
       }
       MinTime += ps[0] + ps[1] + ps[2];
      }
      else
      {
       MinTime += ps[0];
      }
      cout << MinTime << endl;
      delete[]ps;
      ps = NULL;
     }
     return 0;
    }

    这是已经通过的代码

    #include<iostream>
    #include<algorithm>
    using namespace std;
    int MinTime(int *a, int n);

    int main()
    {
     int repeat;
     int datanum;
     int time;
     cin >> repeat;
     while (repeat--)
     {
      cin >> datanum;
      int *ps = new int[datanum];
      for (int i = 0; i < datanum;  i++)
      {
       cin >> ps[i];
      }
      time=MinTime(ps, datanum);
      cout << time << endl;
      delete[]ps;
      ps = NULL;
     }
    }

    int MinTime(int *a, int n)
    {
     sort(a, a + n);
     n--;
     int mintime = 0;
     while (n > 2)
     {
      mintime += min(a[0] + a[1] * 2 + a[n], a[0] * 2 + a[n] + a[n - 1]);
      n -= 2;
     }
     if (n == 0){ mintime = a[0]; }
     else if (n == 1){ mintime += a[1]; }
     else { mintime += a[0] + a[1] + a[2]; }
     return mintime;
    }

    转载于:https://www.cnblogs.com/damaoranran/p/8614832.html

  • 相关阅读:
    POI做报表
    (一) DB2的备份和恢复:准备
    西天取经为节约成本该裁掉哪位?
    python中configpraser模块
    python中subprocess模块
    python中os模块
    python中random模块
    python中time模块和datetime模块
    python中序列化json模块和pickle模块
    迭代器生成器函数的递归调用与二分法
  • 原文地址:https://www.cnblogs.com/twodog/p/12137299.html
Copyright © 2011-2022 走看看