关于 [CSP-S 2022] 假期计划 的一些想法
关于 [CSP-S 2022] 假期计划 的一些想法
洛谷链接
考场算法
这题暴力其实很好想,但是我觉得暴力太低级了,所以就直接跳过了第一步。然而我的分数其实比暴力的还少一点(悲)。
首先,为了判断能吧哪里作为景点,首先跑一次最短路,记录每个点之间的距离。接下来在选择点的时候,我想到了这么一个东西。
整个过程可以从中间断开,分成前后两端,每一段的过程都可以描述为1 - x - y
。最后找解的时候就在这么一个储存的数组里面找就可以了。
然而在这之后我算法的所有瓶颈都出在找的这个地方。在考场上我最后决定用贪心找。把这些状态放到一个优先队里面,然后找能和最大的匹配的另一半。最后得了55分(悲)。
代码
#include <bits/stdc++.h>
using namespace std;struct node {int id, dep; node (int id_, int dep_) {id = id_;dep = dep_;}
};struct res {int p1, p2;unsigned long long num;res (int p1_, int p2_, unsigned long long num_) {p1 = p1_;p2 = p2_;num = num_;}bool operator < (const res x) const {if (num < x.num) return true;else return false;}
};priority_queue <res> pue;
queue <node> que;
int n, m, k, dis[2510][2510];
unsigned long long score[2510];
bool vh[2510];
vector <int> p[2510];void work_dis (int fa, int ori) {dis[fa][fa] = ori;vh[fa] = 1;que.push (node (fa, ori));while (!que.empty()) {node f = que.front();que.pop();for (int i = 0; i < p[f.id].size(); ++i) {if (vh[p[f.id][i]]) continue;vh[p[f.id][i]] = 1;dis[fa][p[f.id][i]] = dis[fa][f.id] + 1;que.push (node (p[f.id][i], dis[fa][f.id] + 1));}}
}void dfs (int pos, int fa, int dep, unsigned long long val) {if (dep > 1) {if (pos != 1) pue.push (res (pos, fa, val));return;}for (int i = 1; i <= n; ++i) {if (dis[pos][i] == -1 || dis[pos][i] > k) continue;dfs (i, pos, dep + 1, val + score[i]);}
}bool check (res x, res y) {if (x.p1 != y.p1 && x.p2 != y.p2 && x.p1 != y.p2 && x.p2 != y.p1) return true;return false;
}int main() {//freopen ("holiday.in", "r", stdin);//freopen ("holiday.out", "w", stdout);memset (dis, -1, sizeof (dis));cin >> n >> m >> k;for (int i = 2; i <= n; ++i)cin >> score[i];for (int i = 1; i <= m; ++i) {int u, v;cin >> u >> v;p[u].push_back (v);p[v].push_back (u);}for (int i = 1; i <= n; ++i) {memset (vh, 0, sizeof (vh));work_dis (i, -1);}dfs (1, 1, 0, 0);res r1 = pue.top();pue.pop();while (!check (r1, pue.top())) pue.pop();cout << r1.num + pue.top().num << endl;//fclose (stdin);//fclose (stdout);return 0;
}
后来
上面的这个代码貌似有点问题,但是我也懒得改了。首先貌似是存状态的时候个别状态方向反了。然后好像在判断两个一半之间能不能联通、有没有重复的时候也有点问题。
但是在这之后我总的方向还是没变的。经过我不懈的尝试 我发现匹配两半的时候,设状态总数为 T T T,那么在前 T T T个分数最大的方案和前 T l o g T TlogT TlogT个最大方案中匹配能通过的点数最多。对此,我的猜想是:大部分有用的解都集中在前面,而这种枚举方式能最大限度地在最优解中匹配,而且数量相对平衡。总之是没啥正理 经过玄学优化枚举范围后的代码能A掉所有的官方数据,而且只有一个民间数据WA掉了。
代码
#include <bits/stdc++.h>
using namespace std;struct node {int id, dep; node (int id_, int dep_) {id = id_;dep = dep_;}
};struct res {int p1, p2;unsigned long long num;bool operator < (const res x) const {if (num > x.num) return true;else return false;}
};queue <node> que;
int n, m, k, dis[2510][2510], cnt, logn[6000010];
unsigned long long score[2510];
bool vh[2510];
res ans[6000010];
vector <int> p[2510];void work_logn() {logn[1] = 0;for (int i = 2; i <= cnt; ++i)logn[i] = logn[i / 2] + 1;
}void work_dis (int fa, int ori) {dis[fa][fa] = ori;vh[fa] = 1;que.push (node (fa, ori));while (!que.empty()) {node f = que.front();que.pop();for (int i = 0; i < p[f.id].size(); ++i) {if (vh[p[f.id][i]]) continue;vh[p[f.id][i]] = 1;dis[fa][p[f.id][i]] = dis[fa][f.id] + 1;que.push (node (p[f.id][i], dis[fa][f.id] + 1));}}
}void dfs (int pos, int fa, int dep, unsigned long long val) {if (dep > 1) {if (pos != 1) ans[++cnt] = {fa, pos, val};return;}for (int i = 1; i <= n; ++i) {if (dis[pos][i] == -1 || dis[pos][i] > k) continue;dfs (i, pos, dep + 1, val + score[i]);}
}bool check (res x, res y) {if (x.p1 != y.p1 && x.p2 != y.p2 && x.p1 != y.p2 && x.p2 != y.p1) return true;return false;
}bool check_link (int x, int y) {if (dis[x][y] <= k && dis[x][y] != -1) return true;return false;
}int main() {memset (dis, -1, sizeof (dis));cin >> n >> m >> k;for (int i = 2; i <= n; ++i)cin >> score[i];for (int i = 1; i <= m; ++i) {int u, v;cin >> u >> v;p[u].push_back (v);p[v].push_back (u);}for (int i = 1; i <= n; ++i) {memset (vh, 0, sizeof (vh));work_dis (i, -1);}dfs (1, 1, 0, 0);work_logn();sort (ans + 1, ans + 1 + cnt);unsigned long long maxn = 0;for (int i = 1; i <= n; ++i)for (int j = i + 1; j <= n * logn[cnt]; ++j)if (check (ans[i], ans[j]) && check_link (ans[i].p2, ans[j].p2) && maxn < ans[i].num + ans[j].num) maxn = ans[i].num + ans[j].num;cout << maxn << endl;return 0;
}
由于 T T T约等于 n 2 n ^ 2 n2,这个方法的时间复杂度差不多是 n 2 l o g n n ^ 2 log n n2logn,时间上问题不大。
然后在洛谷上看到一篇题解,思路和我的差不多,但是在匹配两半的时候边统计边找最大值,时间复杂度一样,但是可以匹配完所有的,具体没看懂。
大致上对于官方数据而言,我的任务完成了。但是真正的算法,还是需要我继续去想一想的。
关于 [CSP-S 2022] 假期计划 的一些想法相关推荐
- [CSP-S 2022] 假期计划
题目传送门 [CSP-S 2022] 假期计划(民间数据) 题目描述 小熊的地图上有 n n n 个点,其中编号为 1 1 1 的是它的家.编号为 2 , 3 , - , n 2, 3, \ldots ...
- 【题解】P8817 [CSP-S 2022] 假期计划(bfs,dfs)
[题解]P8817 [CSP-S 2022] 假期计划 此题作为 CSP-S 的 T1,可以说是相当有难度了.感觉 T1 和 T2 换了个位置.(雾) 我作为场外 VP 选手赛时此题只得了 95pts ...
- [CSP-S 2022] 假期计划题解
假期计划 题目来源: CSP-S 2022 T1 题目描述 小熊计划从家出发去 4 4 4 个不同的景点游玩,完成 5 5 5 段行程后回家:家 → 景点 A A A → 景点 B B B → 景点 ...
- 【spfa】假期计划(jzoj 3936)
假期计划 jzoj 3936 题目大意 给你一个有向图(n,m⩽20000n,m\leqslant 20000n,m⩽20000),现在有一些作为枢纽的点,且保证每一条边的两个点至少有一个是枢纽点,现 ...
- 还没做2022年计划?这个超赞工具送给你
又到了一年制定计划的时候了. 你可能要说,每年的计划在年终回顾时,都实现不了,除了发个朋友圈过下瘾,计划还有什么用呢? 这里其实是2个问题: 1.计划如何实现? 2.计划有什么用? 01 对于计划如何 ...
- 朝花夕拾 - 基金定投回顾及 2022 定投计划
风险提示:本次分析仅供参考,不作为投资策略推荐和收益保证,历史业绩不代表未来表现 基金投资有风险,请谨慎选择! 一 前言 经过 2018/2019 的混乱投资,2020 开始主动分析定投,2021 出 ...
- 2021的计划2022的计划
山高水远,总有新的征程等着你我征服,就像跨过每一座山,趟过每一条河. 2021年末,总想着总结些什么,回头发现,想的太多,做的太少.很多时候,我都是行动上的矮子,思想上的巨人.却深知在未来我们时刻警惕 ...
- 2021年年终总结 2022年计划
嗨,一转眼2021又过去了(貌似每年都是一转眼):最近几年总是给人一种时间过得越来越快的感觉,很神奇.无论你在哪里,在干什么,时间总是奔流不息的向前:2021年很快,2022年或许会更快,时间总是给人 ...
- 计算机假期计划内容,2019寒假计划,超详细学习计划表
[导语]愉快的寒假已经开始了,基于拓宽知识面的目的,按时学习生活,做事有规律,度过一个快乐充实有意义的寒假,因此制定一个合理的寒假学习计划对初中孩子们是非常有必要的.下面为您制定具体计划如下.以下内容 ...
最新文章
- 如何现在就用到 Ubuntu 21.10
- 一文读懂支持向量机SVM(附实现代码、公式)
- mongodb spring 超时时间_spring data mongodb 配置遇到的几个问题
- i7 8750h支持linux,i7 8750H好吗i7 8700和8750H性能差别大吗?
- IDL | 实验一、IDL编码与运行
- win10未能连接网络连接到服务器,win10以太网无法连接网络解决办法
- 如何下载斗鱼回放视频(纯手工)
- 为你的整轨APE音乐制作CUE文件(图文)
- 判断一个很大的数是否是11的倍数(2种做法)
- 业务部门战略规划与支撑部门战略规划
- 机器学习笔记(九)——数据降维:主成分分析法(PCA)
- TAOUP初译稿:提交版本
- 【HBUOJ】暴躁的阿生
- p5.js 和 Processing 的恩怨情仇
- 传感器实训心得体会_传感器实训心得体会
- 一、为什么要做接口自动化,怎样做
- 微软专利展示了具有灵活触控笔的双屏设备
- windows 命令提示符 修改/prompt
- PLSQL-Initialization error
- matlab 学自动驾驶(3) 建立一个驾驶场景并生成综合检测——driving scenario Designer