文章目录
A - Range Swap
题目思路
主要考察循环知识
单纯只用在输出时直接输出其对应的编号
代码
#include <iostream>
#include <algorithm>
using namespace std;
const int maxN = 105;
int a[maxN], b[maxN];
int main(){
int n, p, q, r, s;
cin >> n >> p >> q >> r >> s;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
int cnt = p, cnt1 = r;
for(int i = 1; i <= n; i++){
if(i >= p && i <= q){
cout << a[cnt1++] << ' ';
}
else if(i >= r && i <= s){
cout << a[cnt++] << ' ';
}
else{
cout << a[i] << ' ';
}
}
}
B - Cat
题目思路
主要考察字符串
只需在判断到这个字符是 n 且下一个字符是 a 那么只用在输出一个 y 即可。
代码
#include <iostream>
#include <algorithm>
using namespace std;
const int maxN = 105;
int a[maxN], b[maxN];
int main(){
int n;
string s;
cin >> n >> s;
for(int i = 0; i < n; i++){
cout << s[i];
if(s[i] == 'n' && s[i + 1] == 'a'){
cout << 'y';
}
}
}
C - Rotate and Palindrome
题目思路
主要考察string类型中的成员 substr.
只用枚举一下 a 可以使用的次数,对于每一个新字符串
S
S
S 再枚举一下哪些位不是回文的,最后取一个最小答案
代码
#include <iostream>
using namespace std;
#define int long long
signed main()
{
int n;
int a, b;
cin >> n >> a >> b;
string s;
cin >> s;
string t = s + s;
int ans = LLONG_MAX;
for(int i=0; i<n; i++)
{
string sub = t.substr(i, n);
int cnt = 0;
for(int i = 0; i < n / 2; i++){
if(sub[i] != sub[n - 1 - i]){
cnt++;
}
}
ans = min(ans, cnt*b + i*a);
}
cout << ans << endl;
return 0;
}
D - Money in Hand
题目思路
主要考察背包
数学化题意:给你
n
n
n 个数字,每个数字是
a
i
a_i
ai ,可以用
b
i
b_i
bi次,问是否可以凑出给定的
x
x
x。很容易发现,
b
b
b 个
a
a
a 可以当成单独的数进行处理。所以现在问题变成用
n
n
n 个数组合出
x
x
x。
对于这种问题我们考虑动态规划。先说状态,很简单,
d
p
i
dp_i
dpi
表示
i
i
i 是否能被凑出来。再说转移,对于数
a
a
a,对于
i
∈
[
a
,
x
]
i\in[a,x]
i∈[a,x],有
d
p
i
=
d
p
i
−
a
dp_i=dp_{i-a}
dpi=dpi−a,实现时可以使用或运算,即如果
i
−
a
i-a
i−a 可以被凑出来,那么再加上一个
a
a
a 即可凑出
i
i
i。初始条件
d
p
0
=
1
dp_0=1
dp0=1,都能理解。时间复杂度
O
(
n
×
b
×
x
)
O(n\times b\times x)
O(n×b×x),可以通过。
代码
#include <iostream>
using namespace std;
bool dp[10002];
int main(){
int n, x;
cin >> n >> x;
dp[0] = 1;
for(int k = 1; k <= n; k++){
int a, b;
cin >> a >> b;
for(int i = 1; i <= b; i++){
for(int j = x;j >= a; j--){
dp[j] |= dp[j - a];
}
}
}
cout << (dp[x] ? "Yes" : "No");
return 0;
}
E - Souvenir
题目思路
主要考察弗洛伊德最短路算法
由于本题
n
≤
300
n\le 300
n≤300,所以考虑使用时间复杂度为
O
(
n
3
)
O(n^3)
O(n3)的
F
l
o
y
d
Floyd
Floyd 算法,先求出最短路,再求出最大点权和,但是
F
l
o
y
d
Floyd
Floyd 适合求解边权最最值,所以考虑将点权转成边权,然后用
F
l
o
y
d
Floyd
Floyd 算法求出最值就好了。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
long long n,m,a[305],f[305][305],sum[305][305];
int main() {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
char c;
cin>>c;
if(c=='Y'){
f[i][j]=1,sum[i][j]=a[i]+a[j];
}
else{
f[i][j]=1e18;
}
}
}
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
for(int i=1;i<=n;i++) sum[i][i]=a[i];
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(f[i][k]+f[k][j]==f[i][j]) sum[i][j]=max(sum[i][j],sum[i][k]+sum[k][j]-a[k]);;
cin>>m;
while(m--) {
int x,y;
cin>>x>>y;
if(f[x][y]==1e18) cout<<"Impossible\n";
else cout<<f[x][y]<<" "<<sum[x][y]<<"\n";
}
return 0;
}