A.Suits
分析:模拟题
注意:C++中min函数只能比较两个数之间的大小
min(a,b,c) (x) -------->min(a,min(b,c))
#include <bits/stdc++.h>
using namespace std;
int a, b, c, d, e, f;
long long sum;
int min1, min2;
int main()
{
cin >> a >> b >> c >> d >> e >> f;
if (e <= f)
{
min1 = min(b, min(c, d));
sum += min1 * f;
b -= min1, c -= min1, d -= min1;
if (d > 0)
{
min2 = min(a, d);
sum += min2 * e;
}
}
else if (e > f)
{
min1 = min(a, d);
sum += min1 * e;
a -= min1, d -= min1;
if (d > 0)
{
min2 = min(b, min(c, d));
sum += min2 * f;
}
}
cout << sum << endl;
return 0;
}
B.Blocks
分析:递推。因为题目中不需要求最小次数,我们可以逐个枚举每个位置的方块,每个位置只有操作和不操作两种可能。
#include <bits/stdc++.h>
using namespace std;
int n;
void update(char &c){//转换函数
if (c == 'W') c = 'B';
else c = 'W';
}
bool check(string s, char c){//判断合法
vector<int> ans;//存储操作
for (int i = 0; i < n - 1; i ++ ){//n-1次操作
if (s[i] != c){//不相等,就转换s[i]与s[i+1]
update(s[i]);
update(s[i + 1]);
ans.push_back(i);//把操作装入容器
}
}
if (s[n - 1] != s[0]) return false;//头尾元素不相等即不合法
cout << ans.size() << '\n';//输出操作数
for (auto x : ans)//输出每个操作
cout << x + 1 << ' ';//注意,操作是从1开始的
return true;
}
int main()
{
cin >> n;
string s;
cin >> s;
if (!check(s, 'W') && !check(s, 'B'))//当全变白不行并且全变黑不行,无解
printf("-1\n");
return 0;
}
C.Azamon Web Services
分析: 1.贪心地想:字符串最小肯定是让字典序最小的字母尽量靠前。
2.在让字典序最小的字母尽量靠前的前提下,让字典序大的字母越靠后越优。
#include <bits/stdc++.h>
using namespace std;
typedef pair<char, int> pci;
int n;
set<pci> p;//用set维护一个有序序列,默认为升序
int main()
{
int T;
cin >> T;
while (T--)
{
p.clear();//每次 操作前初始化
string s, t;
cin >> s >> t;
for (int i = 0; i < s.size(); i++)
p.insert({s[i], i});
for (auto &i : s)
{
char mn = (*p.begin()).first;
if (i == mn)
p.erase(p.begin());
else
{
auto it = --p.lower_bound({mn, int(1e9)});//返回大于等于mn的最小的数的前一个数的迭代器
swap(i, s[(*it).second]);
break;
}
}
if (s < t)
cout << s << '\n';
else
puts("---");
}
return 0;
}
D.Shawarma Tent
分析:
本题如果没有 帐篷不能摆放在学校所在地 这一条件,那么就很好想了:我们直接 把帐篷放在学校 不就行了吗?这样人人都能买帐篷了。
可是现在不能直接把帐篷放在学校,其实也很好想。我们直接把帐篷放在学校的上、下、左、右(四周) 就可以了。请看下面这张图:
在这张图中,我们假设帐篷分别在 1,2,3,4四个点上。那么:
1号帐篷将覆盖 区域 #1的所有学生,即覆盖了位于学校左边的所有学生;
2 号帐篷将覆盖 区域 #2的所有学生,即覆盖了位于学校右边的所有学生;
3 号帐篷将覆盖 区域 #3的所有学生,即覆盖了位于学校上边的所有学生;
44 号帐篷将覆盖 区域 #4的所有学生,即覆盖了位于学校下边的所有学生。
我们如果随意移动 1,2,3,4号帐篷的任意一个,就会发现,再也没有其他摆法能像这种摆法一样,覆盖这么广的区域了!
我们只需要在读入时分别统计 1,2,3,4号帐篷 能否覆盖到第 i 个学生。若能,在对应帐篷的 统计变量 上增加 1
最后,输出这四个帐篷统计变量的 最大值,并输出能覆盖到最多学生的帐篷的坐标就可以了!
#include <bits/stdc++.h>
using namespace std;
int n, sx, sy;
int maxx, ans1, ans2, ans3, ans4;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> sx >> sy;
while (n--)
{
int x, y;
cin >> x >> y;
if (x < sx)
ans1++;
if (x > sx)
ans2++;
if (y < sy)
ans3++;
if (y > sy)
ans4++;
}
maxx = max(max(ans1, ans2), max(ans3, ans4));
cout << maxx << '\n';
if (maxx == ans1)
cout << sx - 1 << ' ' << sy;
else if (maxx == ans2)
cout << sx + 1 << ' ' << sy;
else if (maxx == ans3)
cout << sx << ' ' << sy - 1;
else if (maxx == ans4)
cout << sx << ' ' << sy + 1;
return 0;
}
E.Cut and Paste
分析:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
string s;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T--)
{
int x;
cin >> x >> s;
ll ans = s.size();
for (int i = 0; i < x; i++)
{
if (s.size() >= x)
{
ans = (ans + ((ans - i - 1 + mod) % mod) * (s[i] - '1')) % mod;
}
else
{
if (s[i] == '2')
s += s.substr(i + 1);
if (s[i] == '3')
s += s.substr(i + 1) + s.substr(i + 1);
ans = s.size();//更新ans数组
}
}
cout << ans << endl;
}
return 0;
}
F.Portals
分析:DP
#include <bits/stdc++.h>
using namespace std;
const int M = 5e3 + 10;
const int inf = 0x3f3f3f3f;
int a[M], b[M], c[M], f[M][M], t[M];
int n, m, k;
struct node
{
int t, c;
} l[M];
bool cmp(node x, node y)
{
return x.t < y.t;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i] >> b[i] >> c[i];
t[i] = i;//初始化最晚控制时间
}
while (m--)
{
int u, v;
cin >> u >> v;
t[v] = max(t[v], u);//更改最晚控制时间
}
for (int i = 1; i <= n; i++)
{
l[i].t = t[i];
l[i].c = c[i];
}
sort(l + 1, l + 1 + n, cmp);//按照最晚控制时间升序排序
for (int j = 0; j <= k; j++)
f[0][j] = 0;//初始化
for (int j = k + 1; j < M; j++)
f[0][j] = -inf;//初始化成极小值
int idx = 1;//指向当前可控制的城堡
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < M; j++)
f[i][j] = -inf;
for (int j = a[i]; j < M; j++)
f[i][j + b[i]] = max(f[i][j + b[i]], f[i - 1][j]);
while (idx <= n && l[idx].t == i)
{
for (int j = 0; j < M - 1; j++)
f[i][j] = max(f[i][j], f[i][j + 1] + l[idx].c);
idx++;
}
}
int ans = -1;
for (int j = 0; j < M; j++)
ans = max(ans, f[n][j]);
cout << ans << '\n';
return 0;
}
G.Beingawesomeism
#include <iostream>
using namespace std;
int t, n, m;
char a[65][65];
int main()
{
cin >> t;
while (t--)
{
cin >> n >> m;
int sum = 0, f = 4, b1 = 0, b2 = 0, b3 = 0, b4 = 0, sum2 = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
if (a[i][j] == 'A')
sum++;
else
sum2++;
if (((i == 1 && j == 1) || (i == 1 && j == m) || (i == n && j == 1) || (i == n && j == m)) && a[i][j] == 'A')
f = 2; // 角落
if ((i == 1 || j == 1 || i == n || j == m) && a[i][j] == 'A')
f = min(f, 3); // 边上点
if (i == 1 && a[i][j] == 'A')
b1++; // 边上线
if (i == n && a[i][j] == 'A')
b2++;
if (j == 1 && a[i][j] == 'A')
b3++;
if (j == m && a[i][j] == 'A')
b4++;
}
for (int i = 1; i <= n; i++)
{
int num = 0;
for (int j = 1; j <= m; j++)
if (a[i][j] == 'A')
num++;
if (num == m)
f = 2;
} // 中间线判断
for (int j = 1; j <= m; j++)
{
int num = 0;
for (int i = 1; i <= n; i++)
if (a[i][j] == 'A')
num++;
if (num == n)
f = 2;
}
if (b1 == m || b2 == m || b3 == n || b4 == n)
f = 1;
if (sum == 0)
cout << "MORTAL\n"; // 全为P
else if (sum2 == 0)
cout << "0\n"; // 全为A
else
cout << f << endl; // 否则输出
}
}