前两题十分简单。最后一题在赛中想到了使用动态规划,但没有想到dp数组应该是含义。
第一题
思路
简单的模拟即可解决。
code
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
// 处理输入
int n;
cin >> n;
vector<vector<int>> vec(n, vector<int>(n));
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
cin >> vec[i][j];
}
}
int sum = 0;
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
sum += abs(vec[i][j] - vec[j][i]);
}
}
cout << sum << endl;
return 0;
}
第二题
思路
一个选择问题,选择比当前时间cur大的最小时间。
方法一是直接遍历,但这种方法需要计算与当前时间的时间差,处理起来稍有些麻烦。
方法二是利用本题时间模式的特点,先按字典序排序,然后再使用二分搜索法找到比当前时间大的最小时间。这里可以使用STL中的lower_bound()函数来完成二分搜索的过程。
code
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
// 处理输入
string cur;
cin >> cur;
int n;
cin >> n;
vector<string> vec(n);
for(int i = 0; i < n; ++i) {
cin >> vec[i];
}
sort(vec.begin(), vec.end());
cout << *lower_bound(vec.begin(), vec.end(), cur) << endl;
return 0;
}
第三题
思路
看到括号对匹配,第一个想法就是用栈,但实际并没有这么简单,例如对于{[[}这个括号对而言,使用栈就没有办法求出最小改变次数。再换个思路,本题的括号对其实就是字符串,并且要求最小修改,因此可以尝试一下动态规划。
dp数组的含义:
使括号对s在[i, j]范围内合法的最少修改次数为dp[i][j]。
递推公式:
使括号对s在[i, j]范围内合法的最少修改次数可能由两个地方得到,一是使[i+1, j-1]范围的括号对合法的最少修改次数,二是使[i, k]、[k+1, j]两个范围内的括号对合法的最少修改次数。
若s[i]与s[j]相同,则不需要修改:
若s[i]与s[j]相同不相同,且s[i]是左括号,则只需要修改s[j]:
若s[i]与s[j]相同不相同,且s[i]是左括号,则s[i]s[j]都需要修改:
初始化:
dp[i][j]都初始化为0就可以。
遍历顺序:
略
code
#include <bits/stdc++.h>
using namespace std;
int check(char x,char y){
if(x=='['){
if(y!=']') return 1;
return 0;
}
if(x=='('){
if(y!=')') return 1;
return 0;
}
if(x=='{'){
if(y!='}') return 1;
return 0;
}
if(x=='<'){
if(y!='>') return 1;
return 0;
}
if(y!='>'&&y!=']'&&y!='}'&&y!=')') return 2;
return 1;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
string str;
cin >> str;
int n = str.size();
vector<vector<int>> dp(n, vector<int>(n,0));
for(int len=2;len<=n;len+=2){
for(int i=0;i<n-2;++i){
int j=i+len-1;
if(j>n) break;
dp[i][j]=dp[i+1][j-1]+check(str[i],str[j]);
for(int k=i+2;k<j;k+=2){
dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k][j]);
}
}
}
printf("%d\n",dp[0][n-1]);
return 0;
}
补充
1.本题的dp数组含义与递推公式与LC 回文串个数有相似之处。不同在于回文串必须是连续的,所以不需要考虑本题的递推公式中dp[i][k-1]+dp[k][j]的部分。
2.本题是尽可能少地修改原括号对,使得整个括号串匹配。若改为求尽可能少地添加括号,使这些括号匹配起来,应该怎么做?
这就是LC921。
另外再补充LC1541。