A. Primary Task
2.1思路
判断一下前两位是不是 10 ,除去前两位后后面的部分是不是一个大于等于 2 的数
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N = 31;
void solve()
{
int n;
cin >> n;
std::vector<int> v;
while(n)
{
v.push_back(n%10);
n /= 10;
}
if(v.size() <= 2)
{
cout << "NO" << endl;
return;
}
int u = 1;
int res = 0;
for(int i = v.size() - 1; i >= 0 ; i --)
{
if(i == v.size() - 1)
{
if(v[i] != 1)
{
cout << "NO" << endl;
return;
}
}
else if(i == v.size() - 2)
{
if(v[i] != 0)
{
cout << "NO" << endl;
return;
}
}
else
{
for(int i = 0; i <= v.size() - 3; i ++)
{
res += v[i] * u;
u *= 10;
}
break;
}
}
if(v[v.size() - 3] == 0)
{
cout << "NO" << endl;
return;
}
if(res >= 2)
{
cout << "YES" << endl;
return;
}
else
{
cout << "NO" << endl;
return;
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int tt;
cin >> tt;
//tt = 1;
while(tt --)
{
solve();
}
}
B. Seating in a Bus
2.1思路
维护每一个人选座时旁边有没有人即可
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N = 31;
void solve()
{
int n;
cin >> n;
std::vector<int> arr(n + 10);
std::vector<int> judge(n + 10);
for(int i = 1; i <= n; i++)
{
cin >> arr[i];
}
for(int i = 1; i <= n; i++)
{
if(i == 1)
{
judge[arr[i]] ++;
}
else
{
if(arr[i] == n)
{
if(judge[arr[i] - 1] == 0)
{
cout << "NO" << endl;
return;
}
judge[arr[i]] ++;
}
else if(arr[i] == 1)
{
if(judge[arr[i] + 1] == 0)
{
cout << "NO" << endl;
return;
}
judge[arr[i]] ++;
}
else
{
if(judge[arr[i] + 1] == 0 && judge[arr[i] - 1] == 0)
{
cout << "NO" << endl;
return;
}
judge[arr[i]] ++;
}
}
}
cout << "YES" << endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int tt;
cin >> tt;
//tt = 1;
while(tt --)
{
solve();
}
}
C. Numeric String Template
3.1思路
用两个map,字母数字一一映射(映射的数字可能有0,需要特殊处理一下)
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N = 31;
void solve()
{
int n;
cin >> n;
std::vector<int> arr(n + 10);
for(int i = 1; i <= n; i++)
{
cin >> arr[i];
if(arr[i] == 0) {
arr[i] = 1000000001;
}
}
int t;
cin >> t;
while(t --)
{
map<char,int>heap;
map<int,char>heap2;
string s;
cin >> s;
if(s.size() != n)
{
cout << "NO" << endl;
continue;
}
s = ' ' + s;
int ok = 1;
for(int i = 1; i <= n; i ++)
{
if(heap[s[i]] == 0 && heap2[arr[i]] == 0)
{
heap[s[i]] = arr[i];
heap2[arr[i]] = s[i];
continue;
}
else if(heap[s[i]] != 0 && heap2[arr[i]] != 0)
{
if(heap[s[i]] == arr[i] && heap2[arr[i]] == s[i])
{
continue;
}
else
{
ok = 0;
cout << "NO" << endl;
break;
}
}
else
{
ok = 0;
cout << "NO" << endl;
break;
}
}
if(ok == 1)
{
cout << "YES" << endl;
}
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int tt;
cin >> tt;
//tt = 1;
while(tt --)
{
solve();
}
}
D. Right Left Wrong
4.1思路
希望每一个数字被取的次数尽可能多,最优的方案就是找到最左边的 L 和 最右边的 R ,之后,再找到剩余的项中,最左边的 L 和最右边的 R ,以此类推(双指针)O(n)
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N = 31;
void solve()
{
int n;
cin >> n;
std::vector<int> arr(n + 10);
for(int i = 1; i <= n; i++)
{
cin >> arr[i];
}
for(int i = 1; i <= n; i ++)
{
arr[i] = arr[i] + arr[i - 1];
}
string s;
cin >> s;
s = ' ' + s;
int l = 1;
int r = n;
int ans = 0;
while(l <= r)
{
if(s[l] == 'L' && s[r] == 'R')
{
ans += arr[r] - arr[l - 1];
l++;
r--;
}
if(s[l] == 'R')
{
l ++;
}
if(s[r] == 'L')
{
r --;
}
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int tt;
cin >> tt;
//tt = 1;
while(tt --)
{
solve();
}
}
E. Photoshoot for Gorillas
5.1思路
在n*m的矩形中选出所有边长为k的正方形,每个点都有一个选取次数,让最高的猩猩站在选取次数最多的点即可。
那么如何求出每个点的选取次数呢
不难得出对于第 i 行第 j 列的单元格计算方法(见代码)
此题也可用二维差分进行模拟,更好理解
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N = 31;
void solve()
{
map<int,int>heap;
int n,m,k;
cin >> n >> m >> k;
int w;
cin >> w;
std::vector<int> arr(w + 10);
for(int i = 1; i <= w; i ++)
{
cin >> arr[i];
}
vector<int>uu;
sort(arr.begin() + 1, arr.begin() + 1 + w ,greater<int>());
vector<vector<int>>tip(n + 10,vector<int>(m + 10,0));
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= m; j++)
{
int l = min({i,k,n - i + 1,n - k + 1});
int r = min({j,k,m - j + 1,m - k + 1});
uu.push_back(l * r);
}
}
sort(uu.begin(),uu.end(),greater<int>());
int pos = 0;
int res = 0;
for(int i = 1; i <= w; i ++)
{
res += arr[i] * uu[pos];
pos ++;
}
cout << res << endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int tt;
cin >> tt;
//tt = 1;
while(tt --)
{
solve();
}
}
E. Photoshoot for Gorillas
6.1翻译
你们有 n 个矩形,其中 i 个矩形的宽度为 ai ,高度为 bi 。
您可以无限次地执行以下操作:选择一个矩形和其中的一个单元格,然后为其着色。
每次为任意一行或任意一列完全着色,你都可以获得 1 分。你的任务是用尽可能少的操作获得至少 k 分。
假设有一个长方形,宽为 6 ,高为 3 。您可以通过对任意 4 列中的所有单元格着色,从而执行 12 次操作,得到 4 分
6.1思路
n和k ( 1≤n≤1000,1≤k≤100) --矩形的个数和所需的点数。
由n的范围和k的范围,可以想到此题是一个多重背包dp问题,可以预处理出来每一个矩形在最小到最大花费内得到最多的分数,之后套用多重背包dp模板即可。
那么如何处理每一个矩形的最多分数呢,可以想到每次涂一个矩形较短的一边为最优,并且较长的一遍长度会减少1,每贡献1的花费就是min(l,r),然后max(l,r) - 1;当这个矩形缩小到1x1时,便可用1次着色提供两个贡献。
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N = 31;
void solve()
{
int n,k;
cin >> n >> k;
std::vector<int> arr(n + 10);
std::vector<int> brr(n + 10);
for(int i = 1; i <= n; i ++)
{
cin >> arr[i] >> brr[i];
}
int ans = 0;
vector<int>cnt(2 * 1000 + 10);
vector<vector<int>>w(1000 + 10,(vector<int>((1000 + 10) * 2,0)));
vector<vector<int>>c(1000 + 10,(vector<int>((1000 + 10) * 2,0)));
for(int i = 1; i <= n; i ++)
{
cnt[i] = max(arr[i],brr[i]) - 1 + min(arr[i],brr[i]);
}
for(int i = 1; i <= n; i ++)
{
if(arr[i] == 1 && brr[i] == 1)
{
w[i][1] = 2;
c[i][1] = min(arr[i],brr[i]);
if(arr[i] < brr[i])
{
brr[i]--;
}
else
{
arr[i]--;
}
}
else
{
w[i][1] = 1;
c[i][1] = min(arr[i],brr[i]);
if(arr[i] < brr[i])
{
brr[i]--;
}
else
{
arr[i]--;
}
}
for(int j = 2; j <= cnt[i]; j ++)
{
if(arr[i] == 1 && brr[i] == 1)
{
c[i][j] = c[i][j - 1] + 1;
w[i][j] = w[i][j - 1] + 2;
}
else
{
if(arr[i] == 1 || brr[i] == 1)
{
c[i][j] = c[i][j - 1] + 1;
w[i][j] = w[i][j - 1] + 1;
if(arr[i] == 1) brr[i] --;
else arr[i] --;
}
else
{
w[i][j] = w[i][j - 1] + 1;
c[i][j] = c[i][j - 1] + min(arr[i],brr[i]);
if(arr[i] < brr[i])
{
brr[i]--;
}
else
{
arr[i]--;
}
}
}
}
}
vector<int>dp(k + 10,0x3f3f3f3f);
dp[0] = 0;
for (int kx = 1; kx <= n; kx++) // 循环每一组
for (int i = k ; i >= 0; i--) // 循环背包容量
for (int j = 1; j <= cnt[kx]; j++) // 循环该组的每一个物品
dp[i] = min(dp[i],dp[max((int)0,i - w[kx][j])] + c[kx][j]);
if(dp[k] == 0x3f3f3f3f) dp[k] = -1;
cout << dp[k] << endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int tt;
cin >> tt;
//tt = 1;
while(tt --)
{
solve();
}
}