1. 程式人生 > 實用技巧 >HDU 6781 Solo (貪心 + 優先佇列)

HDU 6781 Solo (貪心 + 優先佇列)

Solo

Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 115Accepted Submission(s): 51


Problem Description Alice 和 Bob 準備 solo 一場演算法競賽。

比賽一共有n個題,編號為1,2....,n,對於第i道題,Alice 需要a[i]分鐘寫出一份正確的程式碼,Bob 需要b[i]分鐘寫出一份正確的程式碼。

比賽規則為
1. 每道題第一個通過的人積 1 分,如果兩人同時 AC 該題,只有 Alice 得分。
2. 比賽時長為1018
分鐘。

Alice 和 Bob 的比賽策略都滿足:決定要去做某道題後,會一直解決該題,直到自己或者對手 AC 此題,如果對手 AC 該題,則會立即放棄這題。

Bob 寫完一份正確的程式碼後會立即提交,但 Alice 寫完一份正確的程式碼,可以先暫時不交題,等之後再交(交題的時間忽略不計,任何時間都可以交題)。

另外 Alice 知道 Bob 是按1,2,....,n的順序來依次做題,知道每道題自己需要的時間和 Bob 需要的時間(即a序列和b序列)。

輸出 Alice 最優策略下最多得幾分。

Alice 和 Bob 想題都不需要時間。

Input 第一行一個整數t(1t10)表示t組資料。

每組資料第一行一個整數n(1n2000)表示題數。

第二行n個整數,表示a[1],a[2],...a[n](1a[i]1000000000)

第三行n個整數,表示b[1],b[2],...b[n](1b[i]1000000000)

保證至多隻有一組資料n>100

Output 對於每組資料,一行一個整數表示答案。

Sample Input 2 6 6 6 6 6 6 6 1 1 1 1 1 1 3 1 2 3 5 1 1

Sample Output 1 3 樣例解釋 Case 1 開場直接 rush 最後一題。 Case 2 [0,1) 寫掉第一題,第 5 分鐘交;[1,3) 寫第二題第 6 分鐘交,[3,6) 寫第三題第 6 分鐘交。

Source 2020 年百度之星·程式設計大賽 - 初賽二

Recommend heyang

Statistic|Submit|Discuss|Note

析:這個題和官方題解也不一致,沒有使用動態規劃,由於Alice可以做出題不提交,那麼最優的策略一定是和Bob一起提交,所以Bob的每個題的提交時間都是固定的,然後只需要計算出Alice每個題的最晚結束時間,然後放到一個優先佇列中,時間最長的在最頂層,然後對於每個題,先考慮能不能正常完成,如果能夠按照做完,則直接放到佇列中,如果不能,則需要比較佇列中時間最長的題目比較,如果刪除那個最長的題目,能夠把當前的題目做出來,就把以前的題目刪掉,把當前的題目放進去,為什麼呢,因為當前題目比較短,可以為後面的題目提供更多的時間,這個策略就是最優的,最後佇列中的所有題目都是能得到積分的。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#include <numeric>
#include <unordered_map>
#define debug() puts("++++")
#define print(x) cout<<(x)<<endl
// #define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define be begin()
#define ed end()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define FOR(i,n,x)  for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.in", "r", stdin)
#define freopenw freopen("out.out", "w", stdout)
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e17;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 2e3 + 7;
const int maxm = 2000000 + 7;
const LL mod = 1e9 + 7;
const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1};
const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1};
int n, m;

inline bool is_in(int r, int c) {
  return r >= 0 && r < n && c >= 0 && c < m;
}
inline int readInt(){
  int x;  scanf("%d", &x);  return x;
}

LL a[maxn], b[maxn];

unordered_map<int, int> mp;

struct Task{
  LL l, r, len;
  bool  operator < (const Task &t) const{
    if(len != t.len)  return len < t.len;
    if(r != t.r)  return r > t.r;
    return l > t.l;
  }
};

int main(){
  int T;  scanf("%d", &T);
  while(T--){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)  scanf("%lld", a + i);
    for(int i = 1; i <= n; ++i)  scanf("%lld", b + i), b[i] += b[i-1];
    priority_queue<Task> pq;
    LL time = 0;
    for(int i = 1; i <= n; ++i){
      if(a[i] + time <= b[i]){
        pq.push((Task){time, a[i]+time, a[i]});
        time += a[i];
      }
      else if(!pq.empty()){
        Task t = pq.top();
        if(time + a[i] - t.len <= b[i]){
          pq.pop();
          pq.push((Task){time-t.len, time-t.len+a[i], a[i]});
          time += a[i] - t.len;
        }
      }
    }
    printf("%d\n", pq.sz);


  }
  return 0;
}