A
题意:
在第k个元素后插入x。
大致思路:
遍历数组,到达k时输出x即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
void cincout()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int a[107];
int n, k, x;
int main()
{
cincout();
cin >> n >> k >> x;
for (int i = 1; i <= n; i++)
cin >> a[i];
cout << a[1];
if (k == 1)cout << ' ' << x;
for (int i = 2; i <= n; i++)
{
cout << ' ' << a[i];
if (i == k)cout << ' ' << x;
}
return 0;
}
B
题意:
给出两个长方体对角线的两个顶点,判断两个长方体是否相交。
大致思路:
观察给出的图发现两个长方体如果相交,那么他们的重合部分也是一个长方体,并且发现这个长方体可以用下面图形对角线上顶点和上面图形的对角线下顶点表示出来,所以尝试计算它的长宽高,如果都大于零,说明有相交部分。
注意不能用长宽高先求出了体积,再通过体积是否大于零来判断是否有相交。(赛时我就这么写了,但是这题的数据弱了些,居然过了)
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
void cincout()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int a[107], x;
int main()
{
cincout();
for (int i = 4; i <= 6; i++)
{
a[i] = 99999;
}
int n = 2;
while (n--)
{
for (int i = 1; i <= 3; i++)
{
cin >> x;
a[i] = max(a[i], x);
}
for (int i = 4; i <= 6; i++)
{
cin >> x;
a[i] = min(a[i], x);
}
}
int tmp = min((a[4] - a[1]), min((a[5] - a[2]), (a[6] - a[3])));
if (tmp > 0)
{
cout << "Yes";
}
else cout << "No";
return 0;
}
C
题意:
给定一个长度为N的序列A,在删除k个元素后求出最小值ans=序列中的最大值-序列中的最小值。
大致思路:
相当于在序列中选取N-k个元素,使其中最大值减去最小值的结果最小,贪心的想,排序后连续的一段是最优的,所以先排序,然后遍历每一段长度为n-k的序列。
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
void cincout()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll n, k, minn = 1e17;
ll a[200007];
int main()
{
cincout();
cin >> n >> k;
k = n - k;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++)
{
minn = min(a[i + k - 1] - a[i], minn);
if (i + k - 1 == n)break;
}
cout << minn;
return 0;
}
D
题意:
按照规则不断移动石头,用最小的次数达到结果。
大致思路:
发现数据比较小,尝试暴力搜索,深搜和广搜应该都可以,用string表示状态,map去记录到达这种状态所需的最小次数,如果搜索不到,相当于不能完成,输出-1。
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
void cincout()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int n, cnt, x, a[2], b[2], flag;
string s, t, u, v;
queue<string>q;
map<string,int>mp;
int main()
{
cincout();
cin >> n >> s >> t;
s += "..";
t += "..";
n+=2;
q.push(s);
mp[s] = 1;
while (!q.empty())
{
u = q.front();
if (u == t)
{
break;
}
q.pop();
cnt = mp[u];
for (int i = 0; i < n; i++)
{
if (u[i] == '.')
{
x = i;
break;
}
}
for (int i = 0; i < n - 1; i++)
{
if ( u[i] != '.' && u[i + 1] != '.')
{
v = u;
swap(v[x], v[i]);
swap(v[x + 1], v[i + 1]);
if (mp[v]==0)
{
mp[v] = cnt + 1;
q.push(v);
}
}
}
}
cout << mp[t] - 1;
return 0;
}
E
题意:
给定n个点,n-1条路径。
选择一点去遍历全图,并且使路程最小。
大致思路:
他的路径数为n-1条,可以将图想象成一棵树,那么从一点去遍历这颗树再回到起点所需路程是所有路径×2.而题目没有要求回到起点,意味着从起点到其中一个叶子节点的路程是可以省略的,那么我们尝试去求出其中两叶子结点的最大距离,也就是求二叉树的直径,便能得出答案。
贪心地想理解为有些路径要回头并且×2,有些不用,那么就可以不断地dfs选取最大路径,直到到达终点,所经过的这些路径就是不用回头的。
先选取任意一点,进行一次dfs,最后得出深度最大的那个点,用这个点再进行一次dfs,便能得出不用回头的路径长度。
因为是选取任意的一点,所以要用这个点先去dfs找出深度最深的叶子节点,再进行一次dfs求出直径
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
void cincout()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct Node
{
int to, v;
Node(int x, int y)
{
to = x, v = y;
}
};
ll ans, rt, dep[200007];
int n, a, b, c;
vector<pair<int,int>>v[200007];
void dfs(int st,int to)
{
if (dep[to] > dep[rt])rt = to;
for (int i=0;i<v[to].size();i++)
{
int x = v[to][i].first;
int y = v[to][i].second;
if (x != st)dep[x] = dep[to] + y, dfs(to, x);
}
}
int main()
{
cincout();
cin >> n;
for (int i = 1; i < n; i++)
{
cin >> a >> b >> c;
v[a].emplace_back(b,c);
v[b].emplace_back(a,c);
ans += (ll)2 * c;
}
dfs(0, 1);
dep[rt] = 0;
dfs(0,rt);
cout << ans-dep[rt] << '\n';
return 0;
}