HDU 3233 Download Manager

Description

佳佳要下载资源,一共t个 每个资源有两个参数
s表示大小,p表示已经下了多少
然后Download Manager,是这样的,一次最多能下n个资源,带宽是b
如果目前比n多,那么就按这种顺序排列
s小的先下
s相同p大的先下
如果目前资源数比n少,那么就一起下
同时下载的资源平分带宽b
问耗时t多少?

Algorithm

首先先排序,生成的下载队列就固定了
然后就是模拟,每次把第一个下载完了移除,然后继续下
然后就TLE了
于是用了双向链表
就A了

Code

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxt = 20000 + 9;
const double kmax_r = 20000+9;
struct V
{
  double s;
  int p;
  double r;
  int prev, next;
};
bool cmp(const V &a, const V &b)
{
  if (a.s < b.s || (a.s == b.s && a.p > b.p)) return true;
  return false;
}
V a[maxt];
int main()
{
  int t, n, b;
  for (int ii = 1; ;ii++)
  {
    scanf("%d%d%d", &t, &n, &b);
    if (t == 0 && n == 0 && b == 0) break;
    for (int i = 1; i <= t; i++)
      scanf("%lf%d", &a[i].s, &a[i].p);
    sort(a + 1, a + t + 1, cmp);
    a[0].next = 1;
    for (int i = 1; i <= t; i++)
    {
      a[i].prev = i - 1;
      a[i].next = i + 1;
      a[i].r = a[i].s * (100 - a[i].p) * 0.01;
    }
    a[t + 1].prev = t;
    int tt = t;
    double ans = 0;
    do
    {
      double r_min = kmax_r;
      int p = 0;
      for (int i = 0; i < n; i++)
      {
        p = a[p].next;
        if (a[p].r < r_min) r_min = a[p].r;
      }
      p = 0;
      for (int i = 0; i < n; i++)
      {
        p = a[p].next;
        a[p].r -= r_min;
        if (a[p].r == 0)
        {
          a[a[p].prev].next = a[p].next;
          a[a[p].next].prev = a[p].prev;
          t--;
        }
      }
      ans += (r_min / (double(b) / double(n)));
      if (t < n) n = t;
    }while (n > 0);
    printf("Case %d: %.2lf\n\n", ii, ans);
  }
}

你可能感兴趣的:(HDU 3233 Download Manager)