贪心算法《过河问题》

描述

在漆黑的夜里,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

原文地址:https://www.cnblogs.com/twodog/p/12137299.html