题意:
告诉你今天星期几,问距离周六还有几天。
思路:
直接输出即可。
代码如下:
#include
#include
using namespace std;
int main()
{
string s;
cin >> s;
if (s == "Monday") cout << 5 << endl;
if (s == "Tuesday") cout << 4 << endl;
if (s == "Wednesday") cout << 3 << endl;
if (s == "Thursday") cout << 2 << endl;
if (s == "Friday") cout << 1 << endl;
return 0;
}
题意:
有一个保龄球图,保龄球编号从 1 到 10,其分布如下图所示。
给定一个长度为 10 的 01
串,一一对应每个保龄球,其中 0 表示被击倒,1 表示未被击倒。
问给定的序列是否满足:
第一个保龄球被击倒
存在两列都有未被击倒的保龄球,并且中间存在一列,其中的保龄球全部被击倒。
满足输出 Yes
,不满足则输出 No
.
思路:
先将字符转化为数字存放在 a[]
中,再进行判断:要满足题意,那么 1 号必须为 0
.
接下来逐个分析,要求至少有一列都为 0
,且除了该列之外每一列都至少有一个 1
.
代码如下:
#include
#include
#include
#define ll long long
using namespace std;
int main()
{
string s;
cin >> s;
s = ' ' + s;
int a[20];
for (int i = 1; i <= 10; i++)
a[i] = s[i] - '0';
if (s[1] == '0'){
int sum = 0;
for (int i = 1; i <= 10; i++){
sum += a[i];
}
if (sum == 0){
cout << "No" << endl;
return 0;
}
if (a[3] + a[9] == 0){
cout << "Yes" << endl;
return 0;
}
if (a[2] + a[8] == 0){
cout << "Yes" << endl;
return 0;
}
if (a[5] == 0){
cout << "Yes" << endl;
return 0;
}
if (a[7] == 1 && a[4] == 0){
cout << "Yes" << endl;
return 0;
}
if (a[10] == 1 && a[6] == 0){
cout << "Yes" << endl;
return 0;
}
cout << "No" << endl;
}
else puts("No");
return 0;
}
题意:
给定一个长度为 n
的数组 A,要求找到一段长度为 m
的连续子序列 B,使得 B 中每个数与其序号的乘积之和最大,输出最大值。
思路:
很容易想到用双指针来做,维护一个长度为 m 的滑动窗口,每次移动,都是将后一个数加入并将第一个数移出,还要重新计算当前窗口内的数值,如果每次都这样操作一遍的话,很容易时间复杂度过高导致超时。
我们发现每次移动前面都减少了一个从 l
到 r
的区间和,由此想到可以用一个前缀和数组来维护区间和。
代码如下:
#include
#include
#include
#define ll long long
using namespace std;
const int N = 2e5 + 10;
ll a[N];
ll s[N];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++){
cin >> a[i];
s[i] = s[i - 1] + a[i]; //前缀和
}
ll res = 0;
for (int i = 1; i <= m; i++) //初始窗口,前m个数
res += a[i] * i;
//双指针
ll ans = res;
for (int i = m + 1; i <= n; i++){
int l = i - m + 1, r = i;
res += m * a[r] - (s[r - 1] - s[l - 2]);
ans = max(ans, res);
}
cout << ans << endl;
return 0;
}
题意:
与上题类似,只不过将连续子序列改成了子序列(可以不连续)。
给定一个长度为 n
的数组 A,要求找到一段长度为 m
的子序列 B,使得 B 中每个数与其序号的乘积之和最大,输出最大值。
思路:
n 的范围较大,考虑使用 dp 来做。
定义 f[i][j]
表示前 i 个数中选了 j 个数。
得到状态转移方程为:f[i][j] = max(f[i - 1][j - 1] + a[i] * j, f[i - 1][j])
.
代码如下:
#include
#include
#include
#define ll long long
using namespace std;
const int N = 2010;
int a[N];
ll f[N][N]; //表示前i个数选了j个数
int main()
{
int n, m;
cin >> n >> m;
memset(f, -0x3f, sizeof(f));
for (int i = 1; i <= n; i++){
cin >> a[i];
f[i][0] = 0;
}
f[0][0] = 0; //初始化
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m && j <= i; j++){
f[i][j] = max(f[i - 1][j - 1] + a[i] * j, f[i - 1][j]);
}
}
cout << f[n][m] << endl;
return 0;
}