您的位置:首页 > 其它

cf #345div1 B ----------div2 D

2016-03-09 16:08 309 查看
讲一下题意吧: 对于一个字符串(由h和w组成)初始位置在第一个字母,你可以往右跳,也可以往左跳,跳跃花费a秒,看一个字母需要1s,如果该字母是w,则要多花费bs, 从1往左可以跳到n,从n往右也可以跳到1, 已经看过的字母可以跳过,没看过的必须看! 求:在给出的时间T内。最多可以看到多少个字母。

2016-5-10 回顾:

这题其实就是一个贪心的题目,在给定的时间内,看一个字母会花一定的时间,求最多可看的字母!我们可以先预处理i字母, 看到i字母最少花费的时间,但是好像这样子贪心处理起来会复杂,想不出来很好的解法。因为可以先往右看几个再往左看。 TUT

所以我们肯定需要一些想法来完成 这个东西,如果没有什么好的想法那么自然是先想最朴素的方法, 我们无法解决的问题就是: 存在先往右看几个然后再往左看的情况,那么我们就干脆对于每一个i,先计算从 1向右看到i 所用的时间, 再算一下从i 往左看过去可以看到j(可以看i+ n-j+1张?大概就这个意思)。 for一遍应该取最大值应该就可以了。 所以这题就是一个贪心,遇到卡住的地方就解决卡住的地方,这个卡住的问题暴力即可。

细想:因为 不可能有一种 观看的策略是右,左…..之后还有方向变动的,那样肯定会有可优化的地方。

理论ac完成

这题有点其实有很多种方法过,就是我最开始想的 暴力 二分都可以过,不过我感觉那样子太麻烦了,就跳过了TUT 。 比赛完之后看别人的代码突然发现了一个想法很好,而且根本不会超时的方法。

分析:

先根据给出的字符串,得到两个数组x,y。 x[i]代表从1往右边看到字母i 需要花费的时间,y[i]代表从1往左边看到字母i 需要花费的时间。

那么我们可以直接暴力 (循环一遍 O(n))找到最大值

在for(int i=1;i<=n;i++)的循环里面,我们设置一个j ,对于每一个j 如果 先从1往右到j的时间+从j回到1+再从1向左到j >T 说明无法看到i—–j之外的所有照片,让j++。

这样对于,一个i,我们扫描了所有的j,不会有所遗漏~ 然后如果x[i]>T肯定是不可以的,否则的话可以直接更新最大值。

再写一个for循环, 这一次 是1先往左到j,再从j往右回到1,再往右到j ,其他同理。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define mem(a) memset(a,0,sizeof(a))
#define pfn printf("\n")
#define sf  scanf
#define pf  printf
#define fr(i,n) for(int i=0;i<n;i++)
#define INF 0x7fffffff   //INT_MAX
#define inf 0x3f3f3f3f   //
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
using namespace std;
#define lson l , mid , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
using namespace std;
#define rep(i,s,t) for(int i=int(s); i<int(t); i++)
#define mst(A,k) memset(A,k,sizeof(A))

const int N = 500005;
int n, a, b, T;
char s
;
int x
, y
;

int main() {
//  freopen("1.txt","r",stdin);
scanf("%d%d%d%d",&n,&a,&b,&T);
scanf("%s", s+1);

for (int i = 2; i <= n; ++ i){
x[i] = x[i - 1] + a + 1 + b * (s[i] == 'w');
}
for (int i = n; i >= 2; -- i)
y[i] = y[i + 1] + a + 1 + b * (s[i] == 'w');
T-=1+b*(s[1]=='w');
int ans=0;
for (int i = 1, j = 2; i <= n; i++) {
while (x[i] + y[j] + (i - 1)*a > T && j <= n + 1) j++;
if (x[i] > T) break;
ans = max(ans, i + n - j + 1);
}
for (int i = 1, j = 2; i <= n; ++ i) {
while (x[i] + y[j] + (n + 1 - j) * a > T && j <= n + 1) j ++;
if (x[i] > T)break;
ans = max(ans, i + n - j + 1);
}
ans = min(ans, n);
printf("%d\n", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: