【队内胡策】题解

题面

T1:

T2:

T3:

T4:

题解

T1:

难度不高,但要仔细想想。

思路:

先按截稿时间由小到大排序,这样能使截稿晚的能余出时间照顾截稿早的。

①:从第一个开始,若(当前任务需要的时间+之前的总时间)<=当前任务的截稿时间,则扔进堆里,ans++。

②:若(当前任务需要的时间+之前的总时间)>当前任务的截稿时间,这时要从它前面所有任务中选一个所需时间最长的(记为y)和它比较,
若当前任务所需时间 > y,则不扔进堆中。
若当前任务所需时间 < y,则把y替换成当前任务。

这样能保证时间利用率最高,完成更多的任务。


代码

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int size=200010;

struct edge{
    int a,b;
}l[size];

bool cmp(edge a,edge b)
{
    return a.b==b.b? a.a<b.a :a.b<b.b;//设置排序主要、次要关键字。
}

priority_queue<edge> q;
bool operator <(edge a,edge b)
{
    return a.a<b.a;
}

int main()
{
    freopen("alma.in","r",stdin);
    freopen("alma.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&l[i].a,&l[i].b);//输入数据。
    }
    sort(l+1,l+1+n,cmp);//排序。
    int ans=0,tot=0;//tot记录当前总时间
    for(int i=1;i<=n;i++)
    {
        if(l[i].a+tot<=l[i].b) //当前时间加上总时间小于截稿时间。
        {
            ans++;q.push(l[i]);tot+=l[i].a;
        }
        else//②,这种情况下ans不变。
        {
            edge x=q.top(); q.pop();//取出堆里所需时间最长的。
            tot-=x.a;
            if(l[i].a<x.a) {q.push(l[i]);tot+=l[i].a;}
            else {q.push(x); tot+=x.a;}
        }
    }
    printf("%d",ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T2:


T3:

大家可能没有看懂题面,但看到样例一定就知道这题是什么意思了←_←。

一道字符串DP,在DP中难度不是很大,下面简单介绍一下思路。

思路一:

离线处理,先把给出的文章记录下来,然后想怎样设计状态。
读入用string吧,方便。
可是string的下标是从0开始的怎么办?

    string s="*",t;
    while(cin>>t)//读入 
        s+=t;//把多段字符串拼成一个。
    t="*HELLOWORLD";

这样s就是我们的文章了。

大小写怎么办?
既然上面的HELLOWORLD用了大写,那么我们也全转大写好了。

    for(int i=1;i<=l;i++)//转换为大写 
        if(s[i]>='a')
            s[i]-=32;

大小写搞完了。

怎么设计状态呢?

想啊想~~~

好难啊QAQ

我们可以挨个匹配“helloworld”啊。(重点来了,记笔记记笔记)

于是设计状态f[i][j]表示,原字符串匹配到第 i 个字符,helloworld匹配到第 j 个字符时的方案数 。

先转移f[i][j]=f[i-1][j];

如果当前字符匹配到了helloworld里的某个字符(即s[i]==t[j]),那么就转移f[i][j]+=f[i-1][j-1];
然后把f[i][j]%=MOD;

这样转移部分就写完了。

然后——

i 和 j 的for循环,哪个套在外面呢?想一想。

答案是——

都一样。

“拿s与t匹配”和“拿t与s匹配”得到的结果不是一样么一个大大的#滑稽


代码

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
const int N=500005;
const int mod=1000000007;
int l,f[N][15];//设f[i][j]表示,原字符串匹配到i,helloworld匹配到j的方案数 。
string s,t;//读入用string类型会十分方便。
int main()
{
    s="*";
    while(cin>>t)//读入 
        s+=t;
    t="*HELLOWORLD";
    l=s.length()-1;
    for(int i=1;i<=l;i++)//转换为大写 
        if(s[i]>='a')
            s[i]-=32;
    for(int i=0;i<=l;i++)
        f[i][0]=1;//初始化f[i][0]=1(0<=i<=l)
    for(int i=1;i<=l;i++)
        for(int j=1;j<=10;j++)
        {
            f[i][j]=f[i-1][j];//首先,f[i][j]=f[i-1][j];

            if(s[i]==t[j])//其次,如果s[i]==t[j],就可以转移,f[i][j]+=f[i-1][j-1];
                f[i][j]+=f[i-1][j-1],f[i][j]%=mod;
        }
    printf("%d\n",f[l][10]);
    return 0;
}

运行结果

二维运行结果

思路二:

在线处理,既然我们上面说了“拿s与t匹配”和“拿t与s匹配”得到的结果是一样的,那么我们一个一个的读字符,拿它与“helloworld”比较。

这样的话第二维我们就不需要了=v= 去掉去掉

于是原f[i][j]变成了dp[i]。

然后大小写我们这样:

    if(c==t[i]||c+32==t[i])//t里面是"helloworld"

最后,我们把原先正的搜索顺序改为倒序(原因参考DQS学长的背包问题课件)。

这样我们只需要满足条件时转移dp[i]=dp(dp[i-1]+dp[i])%MOD就可以了。


代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int mod=1000000007;
int main()
{
    freopen("helloworld.in","r",stdin);
    freopen("helloworld.out","w",stdout);
    long long dp[11]={1};
    char c,hello[20]="?helloworld";
    while((c=getchar())!=EOF)
    {
        for(int i=10;i>=1;i--)
            if(c==hello[i]||c+32==hello[i])
                dp[i]=(dp[i-1]+dp[i])%mod;
    }
    cout<<dp[10];
    fclose(stdin);
    fclose(stdout);
    return 0;
}
运行结果

一维运行结果

这里可以很明显的看出第二种方法(共0.19s)在处理大数据时的时间效率要远高于第一种方法(共1.73s)。


T4:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值