继续撸题中…
一、题目大意
题目的大致意思是,在无限长的坐标轴上,有一些圣诞树,坐标由X数组给出,然后有一些人想尽可能的离树近一点,所以题目要求求出一个数组y,表示对应人坐在坐标轴的位置,并且满足所有人距离他最近的圣诞树的距离和最小,题目会给出圣诞树和人的数目,也就是两个数组的长度。
注意,同一个坐标轴位置不能同时有两个物体(both for trees and people)
可能用文字叙述不是很清楚,下面给出题目提供的公式。
其中xi表示各个圣诞树的位置(题目给定),yi表示各个人的位置(需要求解)。
二、题目思路以及AC代码
做完这道题我觉得自己想掐死自己,看到这道题,很自然的就要想,要怎么选位置才能满足条件呢?肯定是找到每个圣诞树的位置,然后挨着圣诞树去填人就好了。比如题目给的样例
2 6
1 5
那么圣诞树的位置是1和5,要求我们安排6个人的位置,那肯定是先填0,2,4,6,因为这几个位置都是距离最近的圣诞树是1的位置,然后接下来找距离最近圣诞树是2的位置,以此类推。
这时候,我就开始犯糊涂了,首先想到的居然不是BFS,我首先想建立两个数组mLeft 和 mRight,分别存每个圣诞树左右两边的坐标,然后直接按照上述的过程模拟即可,但是会TLE,我琢磨为啥呢,因为我第一次遍历O(n)找到了所有距离为1的,第二次遍历O(n)找到了所有距离为2的,所以最后最大距离是多少,我的复杂度就是最大距离乘n,这无疑浪费了很多时间。
和我一开始的想法做对比,你就会发现BFS的时间节省在了哪里。每次不需要再重新遍历,因为queue里面已经存储了。不要说这些你早就知道,因为我也知道,跳出那个思维圈的时候我就发现,这tm就是一道BFS模板题,哭辽,花时间买教训。
下面给出AC代码,顺便也给出一开始我用辅助数组TLE的代码吧,留个纪念:
BFS AC代码:
/*
* Codeforce 1283D:
* @ Author: Johnson
* @ Date: 2020.1.2
*/
#include <iostream>
#include <queue>
#include <vector>
#include <map>
#define MAXN 200010
using namespace std;
struct Point {
int x;
int diff;
};
int dx[2] = {-1, 1};
int n, m;
map<int, bool> mm;
int main() {
cin >> n >> m;
queue<Point> q;
for (int i=0;i<n;i++) {
Point p;
cin >> p.x;
p.diff = 0;
q.push(p);
mm[p.x] = true;
}
vector<int> res;
int cnt = 0;
long long ans = 0;
bool finish = false;
while(!q.empty() && !finish) {
Point cur = q.front(); q.pop();
for (int i=0;i<2;i++) {
int nx = cur.x + dx[i];
if (mm.find(nx) != mm.end()) continue;
Point p;
p.x = nx;
p.diff = cur.diff + 1;
res.push_back(nx);
q.push(p);
mm[nx] = true;
cnt++;
ans += p.diff;
if (cnt >= m) {
finish = true;
break;
}
}
}
cout << ans << endl;
for (int i=0;i<cnt;i++) {
cout << res[i] << " ";
}
cout << endl;
// system("pause");
return 0;
}
辅助数组 TLE代码:
/*
* Codeforce 1283D:
* @ Author: Johnson
* @ Date: 2020.1.2
*/
#include <iostream>
#include <vector>
#include <algorithm>
#define MAXN 200010
using namespace std;
int n, m;
int trees[MAXN];
int mLeft[MAXN], mRight[MAXN];
bool vis_l[MAXN], vis_r[MAXN];
void init() {
for (int i=0;i<MAXN;i++) {
mLeft[i] = 0;
mRight[i] = 0;
vis_l[i] = true;
vis_r[i] = true;
}
}
int main() {
init();
cin >> n >> m;
for (int i=0;i<n;i++) {
cin >> trees[i];
}
sort(trees, trees+n);
for (int i=0;i<n;i++) {
mLeft[i] = trees[i] - 1;
mRight[i] = trees[i] + 1;
}
for (int i=0;i<(n - 1);i++) {
if (mLeft[i+1] < mRight[i]) {
vis_l[i+1] = false;
vis_r[i] = false;
}
else if (mLeft[i+1] == mRight[i]) {
vis_l[i+1] = false;
}
}
vector<int> res;
int num = 0;
bool finish = false;
long long ans = 0;
int diff = 1;
while (true) {
for (int i=0;i<n;i++) {
if (vis_l[i]) {
res.push_back(mLeft[i]);
num++;
mLeft[i]--;
ans += diff;
}
if (num >= m) break;
if (vis_r[i]) {
res.push_back(mRight[i]);
num++;
mRight[i]++;
ans += diff;
}
if (num >= m) break;
}
if (num >= m) break;
diff++;
for (int i=0;i<(n - 1);i++) {
if (!vis_l[i+1] && !vis_r[i]) continue;
if (mLeft[i+1] < mRight[i]) {
vis_l[i+1] = false;
vis_r[i] = false;
}
else if (mLeft[i+1] == mRight[i]) {
vis_l[i+1] = false;
}
}
}
cout << ans << endl;
for (int i=0;i<num;i++) {
cout << res[i] << " ";
}
cout << endl;
// system("pause");
return 0;
}
如果有问题,欢迎大家留言!!!