Problem 2:打地鼠
问题描述:
问题分析:
一道比较简单的dp问题,题目大意中说要将所有的数字从小到大排序,这个用内置的sort函数就可以完成,然后要选择出一个数字子序列,要求任意两个相邻的数之差都不小于给定的d。
可以假设dp[i]表示面对d时,前i个数可以选择出几个数使得题目要求的子序列成立。我们要得到的其实就是dp[n]。思考当我们选择第i个数时,是否需要选择它进入新的子序列,于是分为以下两种情况:
1、不选择第i个数,那么这i个数的满足要求的子序列个数则为dp[i-1]。
2、选择第i个数,那么我们就从第i个数向前扫描,找到第一个与第i个数相差大于等于d的数k,满足要求的子序列个数则为dp[k]+1(需要再加上第i个数)。
综合考虑两种情况,dp[i]的值即为取上述两种情况的最大值。
最后返回dp[n]即可。
本题的代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int a[N],dp[N];
int main()
{
int n,d;
int res=-1;
cin>>n>>d;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
dp[1]=1;
for(int i=2;i<=n;i++)
{
for(int j=i;j>=1;j--)
{
res=-1;
if(a[j]+d<a[i])
{
res=j;
break;
}
}
dp[i]=max(dp[i-1],dp[res]+1);
}
cout<<dp[n];
}
Problem 3:排队打饭
问题描述:
问题分析:
这道题目我在做的时候怎么都觉得是一个操作系统的问题,初试408学魔怔了。
这道题目还是比较简单的,读入给定的所有人的arrive、cost、wait时间后就开始计算。并定义一个nowtime变量用以判断每位同学进入排队队列时是否存在过了等待时间仍未排到的可能
首先第一位同学到达时一定是立刻可以打饭的。那么我们初始化nowtime=arrive[1]+cost[1]。
接下去开始每位同学进入并进行判断,分为以下两种情况:
1、当我进入队列时,我的arrive[i]+wait[i]大于等于nowtime,证明我可以在我之前那位同学打完饭之后达到饭(即wait时间还没有被消耗完),此时我需要将nowtime+=cost[i],即我从nowtime开始打饭,并且打了cost的时间,供我后面一位同学做参考。
2、当我进入队列时,我的arrive[i]+wait[i]小于nowtime,证明在前一位打完前,我还不能打饭,那我必然离开队列,此时不需要修改nowtime,即我离开时我后面同学顶替我的位置,此时的nowtime仍应该是我前一位同学打完饭的时间。此时只需要输出-1即可。
另外,在第一种情况中,如果存在我到达的时间没人打饭,即arrive[i]>nowtime的情况,则需要把以arrive[i]作为nowtime的起始点,开始打饭。
代码如下:
#include <iostream>
using namespace std;
const int N=1e5+10;
int arrive[N],cost[N],wait[N];
int nowtime=0;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>arrive[i]>>cost[i]>>wait[i];
cout<<arrive[1]<<" ";
nowtime = arrive[1]+cost[1];
for(int i=2;i<=n;i++)
{
if(arrive[i]+wait[i]<nowtime) cout<<-1<<" ";
else{
if(nowtime<arrive[i]) nowtime = arrive[i];
cout<<nowtime<<" ";
nowtime += cost[i];
}
}
return 0;
}
复旦大学2020其他的题目仍在更新中……