Codeforces 732D. Exams

题目:Exams

题意:有n天考试,每天可以考对应的科目数,0为当天不考试,考m科目,每科目需要复习天数给出,问完成所有的考试最少用几天?

思路:贪心+二分

           贪心:和实际生活中一样,应先复习考试时间靠前的科目,所以从后遍历天数,累计复习时间,到第一天看是否总复习时间为0,且科目数全部完成!

                       i.e:0 0 1 2 3 0 2 0 1 2   如果从左看,最先考试的是1,2,3但是,1,2后面还有考试天,所以,可以认为3是最先考试科目,所以要从后往前遍历!

           二分:如果按上面的贪心来找,需要从n~1枚举,但是O(n*n)这样就会超时!

                       所以用二分查找n~1之间的数作为每次寻找的最后那天即可!

参考

代码:

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
#define MAX_N 100005
int day[MAX_N],sub[MAX_N],visit[MAX_N];
int n,m;
int fun(int x)
{
    memset(visit,0,sizeof(visit));
    int prepa = 0,num = 0,times = 0;
    for(int i=x;i>0;i--)//倒着来,新出现的科目标记,然后将本科目要复习的时间累计上
    {
        if(!visit[day[i]] && day[i]!=0)
        {
            visit[day[i]] = 1;//标记新科目
            num++;//累计科目数
            prepa += sub[day[i]];//累计需要复习时间
        }
        else
        {
            if(prepa)
                prepa--;//复习一天减一天
        }
        times++;//累计共需多长时间完成
    }
    if(num == m && prepa == 0)//成立条件,科目全考,且全部复习完成
        return times;
return -1;}

int binarySearch()//二分查找从哪天开始倒着来!
{
    int head = 1,tail = n,mid,ans=999999999,temp;
    while(head <= tail)
    {
        mid = (head+tail)/2;
        temp = fun(mid);
        if(temp > 0)
            tail = mid - 1;
        else
            head = mid + 1;
        if(temp != -1)
            ans = min(temp,ans);
    }
    if(ans == 999999999)
        ans = -1;
return ans;}
int main()
{
    while(cin >> n >> m)
    {
        for(int i=1;i<=n;i++)
            cin >> day[i];
        for(int i=1;i<=m;i++)
            cin >> sub[i];
        cout << binarySearch() << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值