A. Rudolf and the Ticket
思路:
- 纯模拟判断即可
以下是代码部分,代码参考来源——jiangly
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n, m, k;
cin >> n >> m >> k;
vector<int> b(n), c(m);
for(int i = 0; i < n; i ++)
cin >> b[i];
for(int i = 0; i < m; i ++)
cin >> c[i];
int ans = 0;
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++)
ans += b[i] + c[j] <= k;
cout << ans << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while(t --)
solve();
return 0;
}
B. Rudolf and 121
思路:
- 从前往后模拟即可
以下是代码部分
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n;
cin >> n;
vector<int> a(n);
for(int i = 0; i < n; i ++)
cin >> a[i];
for(int i = 0; i < n; i ++)
{
if(a[i] < 0)
{
cout << "NO\n";
return ;
}
if(i + 2 >= n && a[i] != 0)
{
cout << "NO\n";
return ;
}
if(a[i] > 0)
{
a[i + 1] -= 2 * a[i];
a[i + 2] -= a[i];
a[i] = 0;
}
}
cout << "YES\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while(t --)
solve();
return 0;
}
C. Rudolf and the Ugly String
思路:
- 从前往后遍历贪心即可
#include<bits/stdc++.h>
using namespace std;
string s;
void solve()
{
int n;
cin >> n >> s;
s = " " + s;
n = (int)s.size();
s = s + " ";
int ans = 0;
for(int i = 3; i < n; i ++)
if(s[i] == 'p')
{
//如果‘p’前面是map
if(s[i - 1] == 'a' && s[i - 2] == 'm') ans ++;
//如果‘p’后面是pie
else if(s[i + 1] == 'i' && s[i + 2] == 'e') ans ++;
}
cout << ans << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
while(t --)
solve();
return 0;
}
- 写法2:
代码参考来源——jiangly
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
int ans = 0;
for(int i = 0; i < n; i ++)
{
if(i + 3 <= n && s.substr(i, 3) == "pie")
ans ++;
if(i + 3 <= n && s.substr(i, 3) == "map")
ans ++;
if(i + 5 <= n && s.substr(i, 5) == "mapie")
ans --;
}
cout << ans << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
while(t --)
solve();
return 0;
}
D. Rudolf and the Ball Game
思路:
- 用动态规划即可
- d p dp dp[第几轮传球][第几个人] = {是否可以被传到}
- 注意,因为取模,所以题目中的 1 − > n 1->n 1−>n看作是 0 − > n − 1 0->n-1 0−>n−1
以下是代码部分
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e3 + 10;
int r[N];
char c[N];
bool dp[N][N];
void solve()
{
int n, m, x;
cin >> n >> m >> x;
for(int i = 1; i <= m; i ++)
cin >> r[i] >> c[i];
//注意初始化为都不能走过
for(int i = 0; i <= m; i ++)
for(int j = 0; j < n; j ++)
dp[i][j] = false;
//注意下标的统一
x --;
//初始时的第x位置是可以被传球传到的。
dp[0][x] = true;
for(int i = 1; i <= m; i ++)
for(int j = 0; j < n; j ++)
{
if(c[i] != '1')
dp[i][j] |= dp[i - 1][(j - r[i] + n) % n];
if(c[i] != '0')
dp[i][j] |= dp[i - 1][(j + r[i] + n) % n];
}
vector<int> v;
for(int i = 0; i < n; i ++)
if(dp[m][i])
v.push_back(i);
cout << v.size() << '\n';
for(auto it : v)
cout << it + 1 << ' ';
cout << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
while(t --)
solve();
return 0;
}
E. Rudolf and k Bridges
思路:
- dp, 得到每一行建造桥所需的最小代价
- 然后求连续的一段行中所需要的最小代价
以下是代码部分,代码参考来源——t0rtik
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
void solve()
{
int n, m, k, d, v;
cin >> n >> m >> k >> d;
vector<i64> a(n);
for(int i = 0; i < n; i ++)
{
//创建一个dp数组,并初始化为无穷
vector<i64> dp(m, 1e9);
//初始的代价为1
multiset<i64> mst = {1};
//第一个位置需要的花费为1
dp[0] = 1;
//输入第一个位置的高度
cin >> v;
for(int j = 1; j < m - 1; j ++)
{
//依次输入水深
cin >> v;
//从0到j的造桥花费的值
dp[j] = *mst.begin() + v + 1;
//维护一个长度为d的区间内的造桥花费最小值
if(j - d - 1 >= 0)
mst.erase(mst.find(dp[j - d - 1]));
//插入0-j区间的造桥花费
mst.insert(dp[j]);
}
//记得输入末尾的1
cin >> v;
//记得加上末尾的1
dp.back() = 1 + *mst.begin();
a[i] = dp.back();
}
//计算建造行连续的桥的时候所需的最小代价
i64 cur = 0;
for(int i = 0; i < k; i ++)
cur += a[i];
i64 mn = cur;
for(int i = k; i < n; i ++)
{
cur += a[i] - a[i - k];
mn = min(cur, mn);
}
cout << mn << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
while(t --)
solve();
return 0;
}