Early in the morning, Farmer John woke up to the sound of splintering wood. It was the cows, and they were breaking out of the barn again!
Farmer John was sick and tired of the cows' morning breakouts, and he decided enough was enough: it was time to get tough. He nailed to the barn wall a counter tracking the number of days since the last breakout. So if a breakout occurred in the morning, the counter would be 00 that day; if the most recent breakout was 33 days ago, the counter would read 33. Farmer John meticulously logged the counter every day.
The end of the year has come, and Farmer John is ready to do some accounting. The cows will pay, he says! But lo and behold, some entries of his log are missing!
Farmer John is confident that the he started his log on the day of a breakout. Please help him determine, out of all sequences of events consistent with the log entries that remain, the minimum and maximum number of breakouts that may have take place over the course of the logged time.
The first line contains a single integer NN (1≤N≤1001≤N≤100), denoting the number of days since Farmer John started logging the cow breakout counter.
The second line contains NN space-separated integers. The iith integer is either −1−1, indicating that the log entry for day ii is missing, or a non-negative integer aiai (at most 100100), indicating that on day ii the counter was at aiai.
If there is no sequence of events consistent with Farmer John's partial log and his knowledge that the cows definitely broke out of the barn on the morning of day 11, output a single integer −1−1. Otherwise, output two space-separated integers mm followed by MM, where mm is the minimum number of breakouts of any consistent sequence of events, and MM is the maximum.
input
4 -1 -1 -1 1
output
2 3
Note
In this example, we can deduce that a breakout had to occur on day 3. Knowing that a breakout also occurred on day 1, the only remaining bit of uncertainty is whether a breakout occurred on day 2. Hence, there were between 2 and 3 breakouts in total.
题目讲述的是,输入n天的计数表,这个计数表的数值代表的是这一天的前几天奶牛的爆发,如果是-1的话,则说明这个计数表上的数值已经丢失了,并且题目说明了计数表是从奶牛第一次爆发的那一天算起,然后题目让我求出奶牛最少的爆发次数以及最多的爆发次数。如果输入的计数表的数值存在矛盾的话,那么输出-1。
首先我们先将-1的情况排除掉,第一天奶牛肯定是会爆发的,所以如果第一天的计数表不为0并且不为-1的话,输出-1。然后把第一天的计数表的数值记为0。
紧接着输入剩下的n-1天的计数表的数值,然后如果第i天的计数表的数值是k的话,然后往前面k天去判断是否矛盾,如果是-1的话,那么就更改为正确的数值,如果存在矛盾的话,那么输出-1。
排除掉-1的情况后,奶牛最少的爆发次数就是计数表上0的个数,最多的爆发次数就是计数表上0的个数加上-1的个数。
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=105;
int a[Maxn];
int main()
{
int n;
scanf("%d",&n);
scanf("%d",&a[1]);
if (a[1]!=-1 && a[1]!=0)
{
printf("-1\n");
return 0;
}
a[1]=0;
for (reg int i=2;i<=n;i++)
{
scanf("%d",&a[i]);
if (a[i]==-1) continue;
for (reg int j=i-a[i];j<i;j++)
{
if (a[j]==-1) a[j]=j-i+a[i];
if (a[j]!=j-i+a[i])
{
printf("-1\n");
return 0;
}
}
}
int minans=0,maxans=0;
for (reg int i=1;i<=n;i++)
{
if (a[i]==0)
{
minans++;maxans++;
}
if (a[i]==-1) maxans++;
}
printf("%d %d\n",minans,maxans);
return 0;
}
In preparation for the upcoming hoofball tournament, Farmer John is drilling his NN cows (conveniently numbered 1…N1…N, where 1≤N≤1001≤N≤100) in passing the ball. The cows are all standing along a very long line on one side of the barn, with cow ii standing xixi units away from the barn (1≤xi≤10001≤xi≤1000). Each cow is standing at a distinct location.
At the beginning of the drill, Farmer John will pass several balls to different cows. When cow ii receives a ball, either from Farmer John or from another cow, she will pass the ball to the cow nearest her (and if multiple cows are the same distance from her, she will pass the ball to the cow farthest to the left among these). So that all cows get at least a little bit of practice passing, Farmer John wants to make sure that every cow will hold a ball at least once. Help him figure out the minimum number of balls he needs to distribute initially to ensure this can happen, assuming he hands the balls to an appropriate initial set of cows.
The first line of input contains NN. The second line contains NN space-separated integers, where the iith integer is xixi.
Please output the minimum number of balls Farmer John must initially pass to the cows, so that every cow can hold a ball at least once.
input
5 7 1 3 11 4
output
2
Note
In the above example, Farmer John should pass a ball to the cow at x=1x=1 and pass a ball to the cow at x=11x=11. The cow at x=1x=1 will pass her ball to the cow at x=3x=3, after which this ball will oscillate between the cow at x=3x=3 and the cow at x=4x=4. The cow at x=11x=11will pass her ball to the cow at x=7x=7, who will pass the ball to the cow at x=4x=4, after which this ball will also cycle between the cow at x=3x=3 and the cow at x=4x=4. In this way, all cows will be passed a ball at least once (possibly by Farmer John, possibly by another cow).
It can be seen that there is no single cow to whom Farmer John could initially pass a ball
so that every cow would eventually be passed a ball.
题目输入n头奶牛的位置,每头奶牛拿到球后便会向左边或者右边最近的奶牛传球,然后题目让我们求出最少用多少个球可以使所有的奶牛全部至少传过一次球。
这个题目就是我们先将奶牛的位置从小到大排序,然后先处理n头奶牛拿到球后会传给哪一头奶牛。
我们预处理完后,对于第i头奶牛,如果这头奶牛向左边传球的话,那么球一定不会传回来这头奶牛的右边,向右边传球也一样,因此满足DP的无后效性,所以我们如果向左传球的话,我们记录球可以传到的最左边的奶牛的编号k,那么对于前i头奶牛最少需要球的数目便等于前k-1头奶牛最少需要球的数目加1。如果向右传球的话,那么我们模拟这个过程,记录传到的最右边的奶牛的编号k,那么对于前k头奶牛需要的最少球的数目便等于前i-1头奶牛需要的最少球的数目加1。
最后输出前n头奶牛需要的最少球数目即可。
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=105;
int x[Maxn],nextt[Maxn],dp[Maxn];
bool sign[Maxn];
int main()
{
int n;
scanf("%d",&n);
for (reg int i=1;i<=n;i++) scanf("%d",&x[i]);
sort(x+1,x+n+1);
nextt[1]=2;nextt[n]=n-1;
for (reg int i=2;i<n;i++)
if (abs(x[i]-x[i-1])<=abs(x[i]-x[i+1])) nextt[i]=i-1;else nextt[i]=i+1;
memset(dp,INF,sizeof(dp));
dp[0]=0;
for (reg int i=1;i<=n;i++)
{
memset(sign,0,sizeof(sign));
sign[i]=1;
int t=nextt[i],minx=i,maxx=i;
while (!sign[t])
{
sign[t]=1;
minx=min(minx,t);
maxx=max(maxx,t);
t=nextt[t];
}
if (minx!=i)
{
for (reg int j=minx;j<=i;j++) dp[j]=min(dp[j],dp[minx-1]+1);
continue;
}
for (reg int j=i;j<=maxx;j++) dp[j]=min(dp[j],dp[i-1]+1);
}
printf("%d\n",dp[n]);
return 0;
}
Farmer John and his personal trainer Bessie are hiking up Mount Vancowver. For their purposes (and yours), the mountain can be represented as a long straight trail of length LL meters (1≤L≤1061≤L≤106). Farmer John will hike the trail at a constant travel rate of rFrFseconds per meter (1≤rF≤1061≤rF≤106). Since he is working on his stamina, he will not take any rest stops along the way.
Bessie, however, is allowed to take rest stops, where she might find some tasty grass. Of course, she cannot stop just anywhere! There are NN rest stops along the trail (1≤N≤1051≤N≤105); the ii-th stop is xixi meters from the start of the trail (0<xi<L0<xi<L) and has a tastiness value cici(1≤ci≤1061≤ci≤106). If Bessie rests at stop ii for tt seconds, she receives ci⋅tci⋅t tastiness units.
When not at a rest stop, Bessie will be hiking at a fixed travel rate of rBrB seconds per meter (1≤rB≤1061≤rB≤106). Since Bessie is young and fit, rBrB is strictly less than rFrF.
Bessie would like to maximize her consumption of tasty grass. But she is worried about Farmer John; she thinks that if at any point along the hike she is behind Farmer John on the trail, he might lose all motivation to continue!
Help Bessie find the maximum total tastiness units she can obtain while making sure that Farmer John completes the hike.
The first line of input contains four integers: LL, NN, rFrF, and rBrB. The next NN lines describe the rest stops. For each ii between 11 and NN, the i+1i+1-st line contains two integers xixi and cici, describing the position of the ii-th rest stop and the tastiness of the grass there.
It is guaranteed that rF>rBrF>rB, and 0<x1<...<xN<L0<x1<...<xN<L. Note that rFrF and rBrB are given in seconds per meter!
A single integer: the maximum total tastiness units Bessie can obtain.
input
10 2 4 3 7 2 8 1
output
15
Note
In this example, it is optimal for Bessie to stop for 77 seconds at the x=7x=7 rest stop (acquiring 1414 tastiness units) and then stop for an additional 11 second at the x=8x=8 rest stop (acquiring 11 more tastiness unit, for a total of 1515 tastiness units).
题目讲述的是,Farmer John和Bessie两个人同时在起点处向山上的终点跑去,Farmer John途中不会停下,一直向终点跑,而Bessie比Farmer John年轻,因此比Farmer John跑得快,途中某些位置有不同鲜味的草,因此Bessie可以中途停下来吃草,但是Bessie不想在某一个时刻落后于Farmer John,于是在保证不落后于Farmer John的情况下,问能够品尝到草的最大价值是多少,对于每一棵草的价值等于这棵草的鲜味乘以Bessie的品尝时间。
由于Bessie跑得比Farmer John快,根据贪心策略,Bessie应该尽量把时间用于品尝鲜味大的草,所以我们首先把草按照鲜味从大到小排序,对于第i个位置的草,如果我们把从起点到这个位置多出来的时间都用于品尝这棵草的话,那么该位置前面的草就不能品尝,对于该位置后面的草,我们就只能从第i个位置到达后面的草的位置多出来的时间去品尝,用一个变量累加品尝每棵草的价值,最后输出答案。
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=1e5+5;
struct Grass
{
ll x,c;
};
Grass grass[Maxn];
bool cmp(Grass a,Grass b)
{
if (a.c!=b.c) return a.c>b.c;
return a.x<b.x;
}
int main()
{
int l,n;
ll rf,rb;
scanf("%d%d%lld%lld",&l,&n,&rf,&rb);
for (reg int i=1;i<=n;i++) scanf("%lld%lld",&grass[i].x,&grass[i].c);
sort(grass+1,grass+n+1,cmp);
ll ans=0,pre=0;
for (reg int i=1;i<=n;i++)
{
if (grass[i].x<pre) continue;
ans+=grass[i].c*(rf-rb)*(grass[i].x-pre);
pre=grass[i].x;
}
printf("%lld\n",ans);
return 0;
}
Bessie the cow is surprisingly computer savvy. On her computer in the barn, she stores all of her precious files in a collection of directories; for example:
bessie/
folder1/
file1
folder2/
file2
folder3/
file3
file4
There is a single "top level" directory, called bessie.
Bessie can navigate to be inside any directory she wants. From a given directory, any file can be referenced by a "relative path". In a relative path, the symbol ".." refers to the parent directory. If Bessie were in folder2, she could refer to the four files as follows:
../file1
file2
../../folder3/file3
../../file4
Bessie would like to choose a directory from which the sum of the lengths of the relative paths to all the files is minimized.
Input
The first line contains an integer N (2≤N≤100,0002≤N≤100,000), giving the total number of files and directories. For the purposes of input, each object (file or directory) is assigned a unique integer ID between 1 and NN, where ID 1 refers to the top level directory.
Next, there will be NN lines. Each line starts with the name of a file or directory. The name will have only lower case characters a-z and digits 0-9, and will be at most 16 characters long. Following the name is an integer, mm. If mm is 0, then this entity is a file. If m>0m>0, then this entity is a directory, and it has a total of mm files or directories inside it. Following mm there will be mm integers giving the IDs of the entities in this directory.
Output
Output the minimal possible total length of all relative paths to files. Note that this value may be too large to fit into a 32-bit integer.
Example
input
8 bessie 3 2 6 8 folder1 2 3 4 file1 0 folder2 1 5 file2 0 folder3 1 7 file3 0 file4 0
output
42
Note
This input describes the example directory structure given above.
The best solution is to be in folder1. From this directory, the relative paths are:
file1
folder2/file2
../folder3/file3
../file4
题目讲述的是,输入n个文件名或者目录名,以及目录当中包括的文件与目录,然后这n个文件或者目录从1到n进行编号,我们可以任意选择一个目录可以得到不同的相对路径,题目我们求出最短的相对路径是多少。
首先我们可以按照题目意思构建一棵树,把每个目录包括的目录以及文件表示出来,在构建树的过程当中,我们要求出每个目录下面有多少个叶子节点,以便于后面的求解,同时我们可以求出各个目录或者文件到达第1个目录的相对路径,然后向第1个目录所包括的目录拓展,对于每个目录的相对路径,等于上一个目录的相对路径减去这个目录包括的文件数乘以这个目录名的长度加一(由于目录名的长度是和'/'算在一起的,所以加上一),然后加上上一个目录包括的其他子目录所包括的文件数乘以3(表示的是字符串"../"的长度)。我们会发现文件其实就是树的叶子节点,所以每个目录包括的文件数便等于所包括的叶子节点数。最后输出最小相对路径长度即可。
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=1e5+5;
vector <int> v[Maxn];
ll dist[Maxn],len[Maxn],dp[Maxn];
int leave[Maxn];
int leaf;
ll ans;
void dfs(int ID)
{
for (reg int i=0;i<v[ID].size();i++)
{
dist[v[ID][i]]=dist[ID]+len[v[ID][i]]+1;
dfs(v[ID][i]);
leave[ID]+=leave[v[ID][i]];
}
if (v[ID].size()) return;
dist[ID]--;
leave[ID]=1;
dp[1]+=dist[ID];
}
void DFS(int ID)
{
ans=min(ans,dp[ID]);
for (reg int i=0;i<v[ID].size();i++)
{
dp[v[ID][i]]=dp[ID]-(len[v[ID][i]]+1)*leave[v[ID][i]]+3*(leaf-leave[v[ID][i]]);
DFS(v[ID][i]);
}
}
int main()
{
int n;
scanf("%d",&n);
for (reg int i=1;i<=n;i++)
{
string st;
cin>>st;
len[i]=st.size();
int m;
scanf("%d",&m);
if (m==0) leaf++;
for (reg int j=1;j<=m;j++)
{
int ID;
scanf("%d",&ID);
v[i].push_back(ID);
}
}
dfs(1);
ans=dp[1];
DFS(1);
printf("%lld\n",ans);
return 0;
}
Early in the morning, Farmer John woke up to the sound of splintering wood. It was the cows, and they were breaking out of the barn again!
Farmer John was sick and tired of the cows' morning breakouts, and he decided enough was enough: it was time to get tough. He nailed to the barn wall a counter tracking the number of days since the last breakout. So if a breakout occurred in the morning, the counter would be 00 that day; if the most recent breakout was 33 days ago, the counter would read 33. Farmer John meticulously logged the counter every day.
The end of the year has come, and Farmer John is ready to do some accounting. The cows will pay, he says! But something about his log doesn't look quite right...
Farmer John wants to find out how many breakouts have occurred since he started his log. However, he suspects that the cows have tampered with his log, and all he knows for sure is that he started his log on the day of a breakout. Please help him determine, for each number of breakouts that might have occurred since he started the log, the minimum number of log entries that must have been tampered with.
The first line contains a single integer NN (1≤N≤1001≤N≤100), denoting the number of days since Farmer John started logging the cow breakout counter.
The second line contains NN space-separated integers. The iith integer is a non-negative integer aiai (at most 100100), indicating that on day iithe counter was at aiai, unless the cows tampered with that day's log entry.
The output should consist of NN integers, one per line. The iith integer should be the minimum over all possible breakout sequences with iibreakouts, of the number of log entries that are inconsistent with that sequence.
input
6 1 1 2 0 0 1
output
4 2 1 2 3 4
Note
If there was only 1 breakout, then the correct log would look like 0 1 2 3 4 5, which is 4 entries different from the given log.
If there were 2 breakouts, then the correct log might look like 0 1 2 3 0 1, which is 2 entries different from the given log. In this case, the breakouts occurred on the first and fifth days.
If there were 3 breakouts, then the correct log might look like 0 1 2 0 0 1, which is just 1 entry different from the given log. In this case, the breakouts occurred on the first, fourth, and fifth days.
And so on.
题目意思跟A题差不多,差别在于这个题目里的奶牛可以更改计数表的数值,并且计数表的数值都是非负数,计数表的数值依然表示前i天奶牛爆发,输入n天计数表的数值,然后让我们求出奶牛在这n天里面,奶牛在从1到n次爆发的情况下,算出来的计数表的数值最少有多少个与输入的这n个数值不同。计数表是从奶牛第一次爆发算起,一直算到第n天。
这个题目一道DP的题目,我们可以先初始化奶牛只有1次爆发的情况,然后输出这种情况有多少个数不同。
我们可以设置一个二维数组dp[i][j],i表示的是第几天,j表示的是奶牛第几次爆发,dp[i][j]表示的是从第i天到第n天这段时间内,奶牛有j次爆发,计数表的数值最少与输入数据有多少个数不同。那么我们会发现对第j次爆发的答案便是dp[1][j],因为第1天奶牛肯定是会爆发的。
按照上面的定义,dp[i][j]只能由dp[k][j-1] (i<k<=n) 转移过来。
于是我们得到状态转移方程:dp[i][j]=min(dp[i][j],dp[k][j-1]+(第i天到第k-1天有多少个数与输入数据不同的个数))。
这里求从第i天到第k-1天有多少个数与输入数据不同的个数可以在状态转移的过程当中求得。
对于这n天里面,奶牛破坏j次的答案便是dp[1][j]。
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int Maxn=105;
int a[Maxn],cnt[Maxn],dp[Maxn][Maxn];
int main()
{
int n;
scanf("%d",&n);
for (reg int i=1;i<=n;i++) scanf("%d",&a[i]);
memset(dp,INF,sizeof(dp));
for (reg int i=n;i>=1;i--)
{
int cnt=0;
for (reg int j=i;j<=n;j++)
if (a[j]!=j-i) cnt++;
dp[1][i]=cnt;
}
printf("%d\n",dp[1][1]);
for (reg int i=2;i<=n;i++)
{
for (reg int j=1;j<=n-i+1;j++)
{
int cnt=0;
for (reg int k=j+1;k<=n-i+2;k++)
{
if (a[k-1]!=k-j-1) cnt++;
dp[i][j]=min(dp[i][j],dp[i-1][k]+cnt);
}
}
printf("%d\n",dp[i][1]);
}
return 0;
}
One of the farming chores Farmer John dislikes the most is hauling around lots of cow manure. In order to streamline this process, he comes up with a brilliant invention: the manure teleporter! Instead of hauling manure between two points in a cart behind his tractor, he can use the manure teleporter to instantly transport manure from one location to another.
Farmer John's farm is built along a single long straight road, so any location on his farm can be described simply using its position along this road (effectively a point on the number line). A teleporter is described by two numbers xx and yy, where manure brought to location xxcan be instantly transported to location yy, or vice versa.
Farmer John wants to transport manure from location aa to location bb, and he has built a teleporter that might be helpful during this process (of course, he doesn't need to use the teleporter if it doesn't help). Please help him determine the minimum amount of total distance he needs to haul the manure using his tractor.
The first and only line of input contains four space-separated integers: aa and bb, describing the start and end locations, followed by xx and yy, describing the teleporter. All positions are integers in the range 0…1000…100, and they are not necessarily distinct from each-other.
Print a single integer giving the minimum distance Farmer John needs to haul manure in his tractor.
input
3 10 8 2
output
3
Note
In this example, the best strategy is to haul the manure from position 3 to position 2, teleport it to position 8, then haul it to position 10. The total distance requiring the tractor is therefore 1 + 2 = 3.
这个题目讲述的是,Farmer John要从a处将牛粪运到b处,然后有一个传送点可以将牛粪快速地从x处运到y处或者从y处运到x处,然后题目问我们Farmer John需要手动运送牛粪的最小距离是多少。
其实我们要将牛粪从a处运到b处,总共有三种方案,第一种是从a处直接运到b处,第二种就是从a处运到x处,然后经过传送点的传送,从y处运到b处,第三种就是从a处运到y处,然后经过传送点的传送,从x处运到b处。以上三种方案求出最小值即为最后答案。
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
int main()
{
int a,b,x,y;
scanf("%d%d%d%d",&a,&b,&x,&y);
int ans=abs(a-b);
ans=min(ans,abs(a-x)+abs(b-y));
ans=min(ans,abs(a-y)+abs(b-x));
printf("%d\n",ans);
return 0;
}
It's winter on the farm, and that means snow! There are NN tiles on the path from the farmhouse to the barn, conveniently numbered 1…N1…N, and tile ii is covered in fifi feet of snow.
Farmer John starts off on tile 11 and must reach tile NN to wake up the cows. Tile 11 is sheltered by the farmhouse roof, and tile NN is sheltered by the barn roof, so neither of these tiles has any snow. But to step on the other tiles, Farmer John needs to wear boots!
In his foul-weather backpack, Farmer John has BB pairs of boots, numbered 1…B1…B. Some pairs are more heavy-duty than others, and some pairs are more agile than others. In particular, pair ii lets FJ step in snow at most sisi feet deep, and lets FJ move at most didi forward in each step.
Unfortunately, the boots are packed in such a way that Farmer John can only access the topmost pair at any given time. So at any time, Farmer John can either put on the topmost pair of boots (discarding his old pair) or discard the topmost pair of boots (making a new pair of boots accessible).
Farmer John can only change boots while standing on a tile. If that tile has ff feet of snow, both the boots he takes off AND the boots he puts on must be able to withstand at least ff feet of snow. Intermediate pairs of boots which he discards without wearing do not need to satisfy this restriction.
Help Farmer John minimize waste, by determining the minimum number of pairs of boots he needs to discard in order to reach the barn. You may assume that Farmer John is initially not wearing any boots.
The first line contains two space-separated integers NN and BB (2≤N,B≤2502≤N,B≤250).
The second line contains NN space-separated integers. The iith integer is fifi, giving the depth of snow on tile ii (0≤fi≤1090≤fi≤109). It's guaranteed that f1=fN=0f1=fN=0.
The next BB lines contain two space-separated integers each. The first integer on line i+2i+2 is sisi, the maximum depth of snow in which pair ii can step. The second integer on line i+2i+2 is didi, the maximum step size for pair ii. It's guaranteed that 0≤si≤1090≤si≤109 and 1≤di≤N−11≤di≤N−1.
The boots are described in top-to-bottom order, so pair 11 is the topmost pair in FJ's backpack, and so forth.
The output should consist of a single integer, giving the minimum number of boots Farmer John needs to discard. It's guaranteed that it will be possible for FJ to make it to the barn.
input
10 4 0 2 8 3 6 7 5 1 4 0 2 3 4 2 3 4 7 1
output
2
这个题目讲述的是,Farmer John需要在雪地上从第一块瓷砖走到第n块瓷砖,数据保证第1块瓷砖和第n块瓷砖没有雪,题目输入n块瓷砖雪的高度,然后Farmer John有B双靴子,每双靴子有最高能够站在多高的雪地上以及最多能够走多少步,然后每双靴子按照输入顺序的倒序依次放入背包,假设Farmer John站在第i块瓷砖上,如果背包里的头一双靴子能够站在雪的最高高度小于第i块瓷砖上雪的高度的话,那么Farmer John会丢掉这双靴子,继续找下一双满足条件的靴子,题目要求的是最少要丢弃多少双靴子才能从第1块瓷砖到达第n块瓷砖。
这个题目我们可能会想到贪心去做,由于题目求的是最少需要丢弃多少双靴子才能到达第n块瓷砖,所以很显然会想到将一双靴子走到不能往前走的时候换靴子,然后最后丢弃多少双靴子即为答案。经过评测,贪心的想法是错误的,这是因为Farmer John可以在每块瓷砖换靴子,而贪心限制了这种自由性,并且中途换靴子可能最终的答案更优。
这个题目的正解是DP,我们定义一个二维数组dp[i][j],其中i表示当前第i块瓷砖,j表示已经丢弃了j-1双靴子,当前穿着第j双靴子,而dp[i][j]则表示一个状态是否存在即可,这是因为在当前状态情况下,答案就是j-1,所以只记录这个状态是否存在即可。在第i块瓷砖,我们可以进行两种操作,一种是换靴子,新的靴子能够站在雪地上最高高度必须超过第i块瓷砖雪的高度,一种是向前走,在该靴子的最大步数范围内,如果靴子能够站在雪地上最高高度大于前面瓷砖的雪的高度的话,那么即可拓展。
最后寻找可以走到第n块瓷砖丢弃最少靴子的存在状态,然后输出这个丢弃靴子数目即可。
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define reg register
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
using namespace std;
const int MaxN=255*2;
const int MaxB=255*2;
struct Root
{
int s,d;
};
Root root[MaxB];
int f[MaxN],dp[MaxN][MaxB];
int main()
{
int N,B;
scanf("%d%d",&N,&B);
for (reg int i=1;i<=N;i++) scanf("%d",&f[i]);
for (reg int i=1;i<=B;i++) scanf("%d%d",&root[i].s,&root[i].d);
memset(dp,0,sizeof(dp));
for (reg int i=1;i<=B;i++) dp[1][i]=1;
for (reg int i=1;i<N;i++)
{
int temp=B+1;
for (reg int j=1;j<=B;j++)
if (dp[i][j])
{
temp=j;
break;
}
for (reg int j=temp;j<=B;j++)
{
if (root[j].s<f[i]) continue;
dp[i][j]=1;
for (reg int k=1;k<=root[j].d && i+k<=N;k++)
if (root[j].s>=f[i+k]) dp[i+k][j]=1;
}
}
int ans=0;
for (reg int i=1;i<=B;i++)
if (dp[N][i])
{
ans=i;
break;
}
printf("%d\n",ans-1);
return 0;
}