题目传送
A Perfect
略
B Common(Easy Version)
C Common(Hard Version)
D Treasure
有一个 n 行 m 列的迷宫, 行数从上到下为 1 到 n, 列数从左到右为 1 到 m, 入口为 (1,1),
Reverie只能向上下左右四个方向行走。迷宫中有若干个宝箱。Reverie想知道,最少需要走多少步,才能找到一个宝箱。
第一行两个正整数 n, m, 表示迷宫的行数和列数。
之后 n 行,每行 m 个字符, ‘.’ 表示该位置是空地, ‘*’ 表示该位置是障碍, ‘#’ 表示该位置有一个宝箱。
保证点 (1,1) 是空地,宝箱所在的格子可以通过。
一行内输出一个整数表示答案,如果没有宝箱或者所有宝箱位置均不可达,输出 -1.
BFS
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mp make_pair
#define pb push_back
ll gcd(ll a,ll b) { return !b?a:gcd(b,a%b);}
ll lcm(ll a,ll b){ return a/gcd(a,b)*b;}
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int cnt = 0;
int r[1000+5][1000+5];
bool visited[1000+5][1000+5];
int res[1000+5][1000+5];
bool bfs(int i,int j){
queue<pair<int,int > > q;
q.push(mp(i,j));visited[i][j] = 1;
pair<int,int> t;
while(!q.empty()){
t = q.front();
i = t.first; j = t.second;
q.pop();
for(int k=0;k<4;k++){
int cx = i+dx[k],cy = j+dy[k];
if(r[cx][cy]&&!visited[cx][cy]){
cnt = res[i][j]+1;
res[cx][cy] = cnt;
visited[cx][cy]=1;
if(r[cx][cy]==2) return true;
else q.push(mp(cx,cy));
}
}
}
return false;
}
int main(){
int n,m;
cin >> n >> m;
memset(visited,0,sizeof(visited));
memset(r,0,sizeof(r));
char c;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin >> c;
if(c=='.') r[i][j] = 1;
else if(c=='#') r[i][j] = 2;
}
if(bfs(1,1)) cout << cnt << endl;
else cout << "-1" << endl;
return 0;
}
E Select
状态转移方程:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int T;
cin >> T;
while(T--){
int n;
cin >> n;
int a[n],dp[n+2];
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
cin >> a[i];
dp[0] = a[0];
dp[1] = max(a[0],a[1]);
for(int i=2;i<n;i++)
dp[i] = max(dp[i-2]+a[i],dp[i-1]);
cout << dp[n-1] << endl;
}
return 0;
}
F Swap(Easy Vesion)
最小交换次数即逆序对数
下面使用两重循环暴力求解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll res = 0 ;
char a[1000005];
int main(){
int t;
cin >> t;
getchar();
while(t--){
res = 0;
scanf("%s",a);
int n = strlen(a);
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
if(a[j]>a[i]){
res ++;
}
}
}
cout << res << endl;
}
return 0;
}
G Swap(Hard Vesion)
数据范围改变
暴力不可行,会超时,使用归并排序求逆序对数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
/*
归并排序求逆序对
*/
ll res = 0 ;
char a[1000005];
char b[1000005];
void merge(char a[],int low,int mid,int high){
int i = low,j = mid +1,k = 0;
while(i<=mid&&j<=high){
if((a[i]-'a')<=(a[j]-'a')) b[k++] = a[i++];
else {
b[k++] = a[j++];
res += (mid-i+1); // 是mid-i+1 而非j-i
}
}
while(i<=mid){
b[k++] = a[i++];
}
while(j<=high){
b[k++] = a[j++];
}
k = 0;
for(i=low;i<=high;i++,k++){
a[i] = b[k];
}
}
void merge_sort(char a[],int low, int high){
int mid;
if(low < high){
mid = (low+high)/2;
merge_sort(a,low,mid);
merge_sort(a,mid+1,high);
merge(a,low,mid,high);
}
}
int main(){
int t;
cin >> t;
getchar();
while(t--){
res = 0;
scanf("%s",a);
merge_sort(a,0,strlen(a)-1);
cout << res << endl;
}
return 0;
}
H Operator
2
3 7
3 6 9
4 6
1 2 3 4
1
0
DFS即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll inf = 0x3f3f3f3f;
const int maxn = 200;
char best[maxn];
void dfs(int a[],int n,int sum,int i,char op[],int tar){
if(i==n){
if(abs(sum-tar)<abs(inf-tar)){
inf = sum;
for(int i=1;i<n;i++)
best[i] = op[i];
}
return ;
}
sum += a[i];
op[i] = '+';
dfs(a,n,sum,i+1,op,tar);
sum -= a[i];
sum -= a[i];
op[i] = '-';
dfs(a,n,sum,i+1,op,tar);
sum += a[i];
}
int main(){
int t;
cin >> t;
getchar();
while(t--){
int n; cin >> n;
ll tar; cin >> tar;
int a[n];
for(int i=0;i<n;i++)
cin >> a[i];
char op[n];
dfs(a,n,a[0],1,op,tar);
ll res = a[0];
for(int i=1;i<n;i++){
if(best[i]=='+')
res += a[i];
else if(best[i]=='-')
res -= a[i];
}
cout << abs(res-tar) << endl;
inf = 0x3f3f3f3f; // 记得修改inf的值
}
return 0;
}