A、最小生成树
小 A 有一张 n 个点的带权无向图,这张无向图非常特别,首先第 i 个点有一个点权 ai,之后这张无向图是一张完全图,且边 (u,v) 的权值为 au+av
现在小 A 想找一个这张图的边权之和最小的生成树,需要你来帮帮他
题解:
每个点都和最小那个点连接形成的树即最小生成树
注意:使用长整形
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn = 1e5 + 15;
ll a[maxn];
int main()
{
int n; cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a, a + n);
ll ans = 0;
for (int i = 1; i < n; i++)
ans += a[0] + a[i];
cout << ans << endl;
return 0;
}
B、病毒感染
有一天clccle和rqy走在某个国家的街头上,机智的rqy却发现周围的行人不太对劲,他们嘴里念念有词,说着"sqn tql!",一边漫无目的的行走,clccle也发现了这一点,却惊讶的发觉这种奇怪的病毒会向周围的城市,最终会感染整个国家,因为网络已经崩溃,所以她们忘记了自己所在的城市,她们唯一知道的是这种病毒是从当前她们所在的城市开始传播的,并且这个国家的所有城市到这个城市的距离和最小(所有道路的距离都为1),现在给定聪明的你一张整个国家的地图,请你帮rqy和clccle找到她们现在可能在这个国家的哪一个城市.
题解:
树的重心板子题
AC代码:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<vector>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = 1e5 + 15;
vector<int>G[maxn];
vector<int>ans[maxn];
int minn;
int d[maxn];
int n, m;
/*
树的重心求法:遍历所有点的子树的大小,然后重心存在的那个点就是最大子树最小的那个点
*/
void dfs(int u, int fa) {
d[u] = 1;
int maxx = 0;
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if (v != fa) {
dfs(v, u);
d[u] += d[v];
maxx = max(maxx, d[v]);
}
}
maxx = max(maxx, n - d[u]);
if (maxx <= minn) {
minn = maxx;
ans[minn].push_back(u);
}
}
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i++) {
int x, y; cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
minn = inf;
dfs(1, 0);
sort(ans[minn].begin(), ans[minn].end());
for (int i = 0; i < ans[minn].size(); i++)
cout << ans[minn][i] << " ";
return 0;
}
C、Shooping
你要买n件物品,其中有一些是凳子。
商场正在举行促销活动,如果购物车中有至少一个凳子,那么你可以半价购买这个购物车中最贵的一个物品。
你有m辆购物车,请最小化你的花费。
题解:
找出min(m,凳子数量),然后对前k大的物品进行打折就好
AC代码:
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
#define ll long long
const int maxn = 1e3 + 15;
bool cmp(double a, double b) {
return a > b;
}
int main()
{
int t; cin >> t;
while (t--) {
double a[maxn];
int num = 0;
int n, m;
cin >> n >> m;
int x;
double ans = 0;
for (int i = 0; i < n; i++) {
cin >> a[i] >> x;
ans += a[i];
if (x == 1)
num++;
}
sort(a, a + n, cmp);
for (int i = 0; i < min(num, m); i++)
ans -= a[i] / 2;
printf("%.1lf\n", ans);
}
return 0;
}
D、铺地毯
为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有n张地毯,编号从1到n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。
题解:
将所有地毯按顺序依次铺上,然后倒序查找最上面的即可
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn = 1e6 + 15;
struct node {
int a, b, g, k;
}a[maxn];
int main()
{
int n; cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i].a >> a[i].b >> a[i].g >> a[i].k;
int x, y; cin >> x >> y;
int is_ok = 0;
for (int i = n; i >= 1; i--) {
if (a[i].a > x || a[i].b > y)
continue;
else if (x <= a[i].a + a[i].g && x >= a[i].a && y >= a[i].b && y <= a[i].b + a[i].k) {
cout << i << endl;
is_ok = 1;
break;
}
}
if (is_ok == 0)
cout << -1 << endl;
return 0;
}
E、金币陷阱
最近,奶牛们热衷于把金币包在面粉里,然后把它们烤成馅饼。第i块馅饼中含有Ni(1<=Ni<=25)块金币,并且,这个数字被醒目地标记在馅饼表面。
奶牛们把所有烤好的馅饼在草地上排成了一个R行(1<=R<=100)C列(1<=C<=100)的矩阵。你现在站在坐标为(1,1)的馅饼边上,当然,你可以拿到那块馅饼里的所有金币。你必须从现在的位置,走到草地的另一边,在坐标为(R,C)的馅饼旁边停止走动。每做一次移动,你必须走到下一列的某块馅饼旁边,并且,行数的变动不能超过1(也就是说,如果现在你站在坐标为(r,c)的馅饼边上,下一步你可以走到坐标为(r-1,c+1),(r,c+1),或者(r+1,c+1)的馅饼旁边)。当你从一块馅饼边经过,你就可以拿走馅饼里所有的金币。当然啦,你一定不会愿意因半路离开草地而失去唾手可得的金币,但,最终你一定得停在坐标为(R,C)的馅饼旁边。
现在,你拿到了一张标记着馅饼矩阵中,每一块馅饼含金币数量的表格。那么,按照规则,你最多可以拿到多少金币呢?
题解:
大佬们拿dp写的,卑微的我看不懂,只好裸dfs了
搜索代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int N = 1e2 + 5;
#define inf 0x3f3f3f3f
int a[N][N];
int vis[N][N];
int R, C;
int dir[3][2] = { {0, 1}, {-1, 1}, {1, 1} };
int dfs(int x, int y) {
if (x == R && y == C)
return 0;
if (vis[x][y])
return vis[x][y];
vis[x][y] = -inf;
for (int i = 0; i < 3; i++) {
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if (xx >= 1 && xx <= R && yy >= 1 && yy <= C)
vis[x][y] = max(vis[x][y], dfs(xx, yy) + a[xx][yy]);
}
return vis[x][y];
}
int main()
{
cin >> R >> C;
for (int i = 1; i <= R; i++)
for (int j = 1; j <= C; j++)
cin >> a[i][j];
int ans = dfs(1, 1) + a[1][1];
cout << ans << endl;
return 0;
}
dp代码:
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define ll long long
const int N = 1e2 + 5;
#define inf 0x3f3f3f3f
int a[N][N], dp[N][N];
int R, C;
int main()
{
cin >> R >> C;
for (int i = 1; i <= R; i++)
for (int j = 1; j <= C; j++)
cin >> a[i][j];
dp[1][1] = a[1][1];
for (int i = 2; i <= C; i++) {
for (int j = 1; j <= R; j++) {
if (dp[j][i - 1] != 0)
dp[j][i] = max(dp[j][i], dp[j][i - 1] + a[j][i]);
if (dp[j + 1][i - 1] != 0)
dp[j][i] = max(dp[j][i], dp[j + 1][i - 1] + a[j][i]);
if (dp[j - 1][i - 1] != 0) {
dp[j][i] = max(dp[j][i], dp[j - 1][i - 1] + a[j][i]);
}
}
}
cout << dp[R][C] << endl;
return 0;
}