陶陶摘苹果 & 送礼
都是模拟题就不贴代码了
坏掉的项链
题意:从项链的一个地方拆开,从一端收集相同颜色的珠子,白色的珠子可以看成是红色也可以看成是蓝色,问从两端收集的珠子个数最多为多少
题解:模拟记录就行,但是有一些小细节要处理一下,首先是赋值一串字符串在后面(首尾相连),记录下要搜索的珠子颜色,然后遇到w(白色珠子)就记录个数,若不是就加到当前的记录里并清空w,遇到不同的珠子时比较最大值并记录下一个要搜索的颜色还有最大值。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std ;
int main(){
int n ; cin >> n ;
string s ; cin >> s ;
s = s + s ;//项链是环形的所以复制一份
//cnt last记录当前和上一次的最大值,mx记录断开的最大值,w记录白色珠子的个数
int cnt=0 , w=0 , mx=0 , last=0 ;
char ch = s[0] ;
for(int i=0 ; i < s.length() ; ++ i){
if(s[i] == 'w') ++w ;
else if (s[i] == ch){
cnt += w+1 , w = 0 ;
}
else{
if(mx < last+cnt+w)
mx = last+cnt+w ;
last=cnt , cnt =0 , ch = s[i] , -- i ;
}
}
if(mx < last+cnt+w)
mx = last+cnt+w ;
cout << min(mx,n) << endl ;
return 0 ;
}
守望者的逃离
题意:有一个人在岛上,该岛在t秒后将会沉没,该人距离出口有s米并且有m点魔法值,每秒可以跑17米,如果放技能会消耗10点魔法值但是可以一秒内移动60米,原地不动休息的时候每秒恢复4点的魔法值,如果该人能够逃离小岛则打印出Yes还有最早逃出的时刻,否则打印出No和能跑最远的距离。
题解:f[i]为第i秒的时候能跑的最远的距离,先考虑最快的放技能,能放就先放,不能就休息,然后再用跑步插缝比较最大值。
#include <cstdio>
#include <algorithm>
using namespace std ;
const int N = 3e5 + 5 ;
int f[N] ;
int main(){
int m , s , t ;
scanf("%d%d%d",&m,&s,&t) ;
for (int i=1 ; i <= t ; ++ i){
if(m >= 10)
f[i] = f[i-1]+60 , m -= 10 ;
else
f[i]=f[i-1] , m += 4 ;
}
for(int i=1 ; i <= t ; ++ i)
f[i] = max(f[i],f[i-1]+17) ;
for(int i=1 ; i <= t ; ++ i){
if(f[i] >= s){
printf("Yes\n%d\n",i) ;
return 0 ;
}
}
printf ("No\n%d\n",f[t]) ;
return 0 ;
}
P1108 低价购买
题意:求最长下降子序列和以及其方案数
题解:最长下降子序列就是经典的dp了,主要是这个方案数,其实就是在求出最长下降子序列dp[]的基础上求各个方案数f[] , 首先将dp[i]==1的赋值为1(单独一个是一个方案),如果后一个的长度为前一个的长度加一并且其值小于前一个(dp[i]==dp[j]+1&&a[i]<a[j])这个就是可以替换的方案所以f[i] += f[j] , 但是要注意当(dp[i]==dp[j]+1&&a[i]==a[j])时f[i]=0,值相同只能替换一个所以方案数赋值为0去重。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <iostream>
using namespace std ;
const int N = 5005 ;
int a[N] ,dp[N] ,f[N] ;
int main(){
int n ; cin >> n ;
for(int i=1 ; i <= n ; ++ i)
cin >> a[i] ,dp[i]=1 ;
for(int i=2 ; i <= n ; ++ i){
for(int j = 1 ; j < i ; ++ j)
if(a[i] < a[j])
dp[i] = max(dp[i],dp[j]+1) ;
}
int mx = *max_element(dp+1,dp+n+1) , cnt = 0 ;
for(int i=1 ; i<=n ; ++ i){
if(dp[i]==1) f[i]=1 ;//单独一个是一个方案
for(int j=1 ; j < i ; ++ j){
if(dp[i]==dp[j]+1&&a[i]<a[j])//可替换的值
f[i] += f[j] ;
else if(dp[i]==dp[j]&&a[i]==a[j]) f[i]=0 ;//相同的值去重
}
if(dp[i] == mx) cnt +=f[i] ; //等于最长序列记录方案数
}
cout << mx << " " << cnt << endl ;
return 0 ;
}