【6】Kick Start 2019 - Round E Code - Eat Switcher

题目描述:

Problem

Umon is a foodie coder. Do you know what two activities that he loves the most? Of course, coding and eating! He always spends the whole day doing only those two activities. However, he thinks that some times of the day are better spent coding, and others are better spent eating.

To illustrate this problem, Umon divides his day into S time slots. During the i-th time slot, if Umon codes 100% of the time, he will achieve Ci units of coding. On the other hand, if he eats 100% of the time, he will achieve Ei units of eating. But of course, Umon can also use only a fraction of the time for coding, and the remaining for eating. Formally, he will choose a real number f (0 ≤ f ≤ 1), code for f of the time, and use the remaining (1 - f) time to eat. This way, he will achieve f × Ci units of coding and (1 - f) × Ei units of eating. The total amount of coding Umon achieves for the day is simply the sum of all units of coding he achieved in each of the time slots. The total amount of eating is calculated in a similar way.

Umon needs to plan his schedule for the next D days. On the i-th day, he needs to achieve at least a total amount of Ai units of coding and Bi units of eating. For each day, determine whether there is a way for Umon to achieve his target.

Input

The first line of input gives the number of test cases, TT test cases follow. Each test case begins with a line containing two integers D and S, the number of days and the number of time slots in a day, respectively.

Then S lines follow, each describing a time slot. The i-th line contains two integers Ci and Ei, the amount of coding units achieved if Umon codes for 100% of the time slot, and the amount of eating units achieved if he eats for 100% of the time slot, respectively.

Then D lines follow, each describing a day. The i-th line contains two integers Aiand Bi, the minimal total amount of coding and eating that needs to be achieved on that day.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is a string with D characters, where the i-th character is Y if there exists a schedule that can fulfill the target for the i-th day, otherwise it should be N.

Limits

Time limit: 20 seconds per test set.
Memory limit: 1GB.
1 ≤ T ≤ 100.
1 ≤ Ci ≤ 104, for all i.
1 ≤ Ei ≤ 104, for all i.
0 ≤ Ai ≤ 108, for all i.
0 ≤ Bi ≤ 108, for all i.

Test set 1 (Visible)

1 ≤ S ≤ 2.
1 ≤ D ≤ 10.

Test set 2 (Hidden)

For at least 90% of the test cases:
1 ≤ S ≤ 103.
1 ≤ D ≤ 103.

For all test cases:
1 ≤ S ≤ 105.
1 ≤ D ≤ 105.

Sample


Input 
 

Output 
 
2
4 2
3 8
6 10
0 18
3 13
10 0
7 3
1 2
4 4
4 4
0 0

  
Case #1: YYNY
Case #2: Y

  

In the first sample case, there are 4 days and 2 time slots for each day.

  • For day 1, Umon can just eat 100% for both time slots, and therefore achieving a total of 0 units of coding and 8 + 10 = 18 units of eating, thus reaching the target.
  • For day 2, Umon can eat 100% of the time for the first time slot, and use 50% of the second time slot for coding and 50% for eating, achieving a total of 0 × 3 + 0.5 × 6 = 3 units of coding, and 1 × 8 + 0.5 × 10 = 13 units of eating, thus reaching the target.
  • For day 3, it is impossible to get a total of 10 units of coding.
  • For day 4, there are an infinite amount of ways to achieve the target. One possible strategy is to code 42% (and eat 58%) in the first time slot, then code 98.76% (and eat 1.24%) in the second time slot. That strategy yields a total of 0.42 × 3 + 0.9876 × 6 = 7.1856 units of coding, and 0.58 × 8 + 0.0124 × 10 = 4.764 units of eating.

Thus, the answer should be YYNY.

In the second sample case, note that the value of characteristics for the time slots may not necessarily be different from each other.

解题思路:

给定不同时序下可以完成的代码和吃饭任务,然后给定一天的代码和吃饭目标,问当日是否可以完成该目标,在同一个时序内可以进行多个任务分配。这道题的关键点有如下几个:

1、首先将不同的时序进行排序,每个时序优先完成的任务不同,如果C/E大,则优先完成代码任务效率最高。注意E可能出现0的情况,因此在排序的时候可以使用 C1 * (ll)E2 > C2 * (ll)E1 。注意此时应该将int转为long long 类型。

2、计算得到排序后的数组,可以得到code和food分别累计的前缀数组,即从左到右累加code,从右向左累加food。

3、对待每一天的任务,利用二分查找搜索code到哪一个时序可以完成任务,剩余的时序用来进行food任务。

4、判断是否满足条件,输出。

5、vector使用emplace_back代替push_back可以压入一个数据结构的多项数据。

6、二分查找的思想需要掌握。

 

代码如下:

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

bool sortpii(pii a, pii b){
    return a.first * (ll)b.second > b.first * (ll)a.second;
}

void solve(){
    int D, S;
    cin>>D>>S;

    vector<pii> ts; //time slot
    pii CE;
    for (int i = 0; i < S; i++){
        cin>>CE.first>>CE.second;
        ts.push_back(CE);
    }
    sort(ts.begin(), ts.end(), sortpii);

    vector<ll> codac;
    vector<ll> fodac;
    codac.push_back(0);
    fodac.push_back(0);
    for (int i = 0; i < S; i++){
        codac.push_back(codac[i] + ts[i].first);
        fodac.push_back(fodac[i] + ts[S - i - 1].second);
    }

    int code, food;
    int lhs, rhs;
    int mid;
    double f;
    for (int i = 0; i < D; i++){
        cin>>code>>food;
        if (codac[S] < code || fodac[S] < food){
            cout<<"N";
            continue;
        }
        lhs = 0;
        rhs = codac.size() - 1;
        while(lhs != rhs){
            mid = (lhs + rhs + 1) / 2;
            if (codac[mid] < code){
                lhs = mid;
            }
            else {
                rhs = mid - 1;
            }
        }

        if (lhs == codac.size() - 1){
            if (codac[lhs] >=code && fodac[0] >= food){
                cout<<"Y";
            }
            else{
                cout<<"N";
            }
        }
        else{
            int idx = lhs;
            double codeCurr = codac[idx];
            double codeNeed = code - codeCurr;
            double f = codeNeed / ts[idx].first;
            double foodCurr = (1 - f) * ts[idx].second + fodac[S - idx - 1];
            if (foodCurr >= food){
                cout<<"Y";
            }
            else{
                cout<<"N";
            }
        }

    }

    cout<<endl;
}

void casesol(){
    int T;
    cin>>T;
    for (int i = 1; i <= T; i++){
        cout<<"Case #"<<i<<": ";
        solve();
    }
}
int main(){
    freopen("data.txt", "r", stdin);
    casesol();
    return 0;
}

在打比赛的时候提交过一版,但是不知道为什么报错,一直找不到原因,崩溃 。。。 先记录一下,等有时间再纠错,求哪位好心人可以帮我康康, 呜呜

错误代码如下:

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

bool sortpii(pii a, pii b){
    return a.first * (ll)b.second > b.first * (ll)a.second;
}

void solve(){
    int D, S;
    cin>>D>>S;

    vector<pii> ts; //time slot
    pii CE;
    for (int i = 0; i < S; i++){
        cin>>CE.first>>CE.second;
        ts.push_back(CE);
    }
    sort(ts.begin(), ts.end(), sortpii);

    vector<ll> codac;
    vector<ll> fodac;
    codac.push_back(0);
    fodac.push_back(0);
    for (int i = 0; i < S; i++){
        codac.push_back(codac[i] + ts[i].first);
        fodac.push_back(fodac[i] + ts[S - i - 1].second);
    }

    int code, food;
    int lhs, rhs;
    int mid;
    double f;
    for (int i = 0; i < D; i++){
        cin>>code>>food;
        if (codac[S] < code || fodac[S] < food){
            cout<<"N";
            continue;
        }
        
        for (lhs = 1; lhs <= S; lhs++){
            if (codac[lhs] > code)
                {break;}
        }
        
        if (lhs == S){
            f = ((double)codac[lhs] - (double)code)/(double)ts[lhs-1].first;
            if (f * (double)ts[lhs - 1].second + 1e-6 >= food){
                cout<<"Y";
                continue;
            }
            else{
                cout<<"N";
                continue;
            }
        }
        else{
            f = ((double)code - (double)codac[lhs - 1])/(double)ts[lhs -1].first;
            if (fodac[S - lhs] + (1 - f) * (double)ts[lhs -1].second + 1e-6>= food ){
                cout<<"Y";
                continue;
            }
            else{
                cout<<"N";
                continue;
            }
        }
    }

    cout<<endl;
}

void casesol(){
    int T;
    cin>>T;
    for (int i = 1; i <= T; i++){
        cout<<"Case #"<<i<<": ";
        solve();
    }
}
int main(){
    freopen("data.txt", "r", stdin);
    casesol();
    return 0;
}

三十年河东,三十年河西

莫欺少年穷

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值