题面(过于冗长,主要是对通信题的一些解释)

题解

1.通信题什么意思

并不是两个程序同时跑。

而是你写两个不能单独运行的子程序,然后由评测方调用,检查是否通过数据点。

通信题一般会给你很多函数,有些是你可以不用手写定义就使用的函数(一般在“有效文件名.h”里定义了,你得在代码里加上它的头文件,用""而不是<>),这是第一类,有些是你需要定义其内容的函数(这类函数将被评测方调用,用以检查是否通过),这是第二类。

所以,形象地说,你要写的算法部分得被拆分到各个第二类函数里,适应题目告诉你的调用顺序。你的两个程序是死的,它们没有主函数,只会在被评测方调用时“激活”特定的函数并运行。此时你可能就不得不把算法中的一些循环展开,多加些 if, else 把算法拆分到不同函数中 。

因此,大多通信题都可以算是模拟题了吧。

2.此题题解

它要求最短路,那我们就跑个Dijkstra好了。算法过程应该都清楚:

  1. 找到目前没计算过的距离起点最近的转移点。
  2. 更新邻接点的最短路。
  3. 重复此过程直到所有点都计算过。

此时的局限是,A 和 B 任一方都不知道所有的边,只知道一部分。其实这个很好办,对于第二步,我们就利用自己知道的边转移就行了,然后为了保证第一步得到的是正确的转移点和最短路,需要 A 和 B 进行一次交流。

先向对方发送自己计算的转移点最短路长度,然后当一方知道了对方的最短路长度,就可以比较得出谁的转移点是正确的。

比较得出自己的转移点更优的话,需要向对方发送自己的转移点编号,因为对方此时只知道你的更优,以及转移点最短路长度是多少,但是不知道转移点具体的编号。

比较得出对方转移点更优的话,则等待对方发送的编号。

传输的数据长度是

n

(

log

⁡

n

+

2

∗

log

⁡

(

w

∗

n

)

)

n(\log n+2*\log (w*n))

n(logn+2∗log(w∗n)) 的,长度会超过 58000。我们加一个小优化:每次发送最短路长度 - 上一个转移点的最短路。由 Dijkstra 算法的性质可以证明这个数是不超过 w 的数据范围的,那么数据长度就优化到了

n

(

log

⁡

n

+

2

∗

log

⁡

w

)

n(\log n+2*\log w)

n(logn+2∗logw) ,刚好卡到 58000 .

CODE

实现

由于 A 和 B 的代码类似,就拿 A 说吧。

我们会在 InitA() 函数中知道 n,m 和边的信息,因此在这个函数中初始化算法,我们把要用到的信息存到全局变量中:

InitA(...) {
记录 n,m;
存边, 建图;
更新 0 号点的邻点最短路;
last_ans = 0;
开始 dijkstra:
交流: 发送转移点最短路...
}

然后呢?我们发现接收函数是外面的 ReceiveA() ,此时就不得不结束 InitA() 了啊,因此我们得多用一些变量记录算法流程,当前接收信息的目的,接收的完整度等。在 ReceiveA() 中我们得判断当前接收的信息是否完整(因为每次只有一个 bool ,得接收多次),若已100%接收,则把下一次接收信息之前的操作都做完,退出函数(等待下一次被调用)。

还是比较考验模拟能力的。

为了防止变量重名编译错误,需要把全局变量等放进空 namespace 里。

A.h 和 B.h 中是对各个函数的声明。

A.cpp

#include "A.h"
#include <bits/stdc++.h>
using namespace std;
namespace {
#define MAXN 2005
#define DB double
#define LL long long
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
int n,m,s,o,k;
struct it{
int v,w;it(){v=w=0;}
it(int V,int W){v=V;w=W;}
};
vector<it> g[MAXN];
int dp[MAXN];
int tre[MAXN<<2],M;
int bing(int a,int b) {return dp[a] < dp[b] ? a:b;}
void maketree(int n) {M=1;while(M<n+2)M<<=1;}
void addtree(int x,int y) {
int s = M+x;tre[s] = y; s >>= 1;
while(s) tre[s] = bing(tre[s<<1],tre[s<<1|1]),s >>= 1;
}
int findall() {return tre[1];}
int CNT = 0,ctnm = 0,recnm = 0;
int flag = 0;
void sendnmA(int x,int bt) {
for(int i = bt-1;i >= 0;i --) {
bool tmp = (x & (1<<i));
SendA(tmp);
}return ;
}
int t,las = 0;
void calcu() {
for(int i = 0;i < (int)g[t].size();i ++) {
int y = g[t][i].v,w = g[t][i].w;
if(dp[t] + w < dp[y]) {
dp[y] = dp[t] + w;
addtree(y,y);
}
}
addtree(t,0);
CNT ++;
flag = 1;
t = findall();
if(CNT >= n || !t) {flag = -1;return ;}
sendnmA(min(511,dp[t]-las),9);
return ;
}
}
void ReceiveA(bool x) {
recnm <<= 1;recnm += x;
ctnm ++;
if(flag == 1 && ctnm >= 9) {
if(recnm+las >= dp[t]) {
sendnmA(t,11);
las = dp[t];
ctnm = recnm = 0;
calcu();
}
else {
flag = 0;
las = recnm + las;
ctnm = recnm = 0;
}
return ;
}
if(flag == 0 && ctnm >= 11) {
t = recnm;dp[t] = las;
ctnm = recnm = 0;
calcu();
return ;
}
return ;
}
void InitA(int N, int M, vector < int > U, vector < int > V, vector < int > W) {
n = N;m = M;
for(int i = 1;i <= m;i ++) {
s = U[i-1]+1; o = V[i-1]+1; k = W[i-1];
g[s].push_back(it(o,k));
g[o].push_back(it(s,k));
}
maketree(n);
for(int i = 0;i <= n;i ++) dp[i] = 0x7f7f7f7f;
dp[1] = 0;t = 1;las = 0;
calcu();
return ;
}
vector < int > Answer() {
vector < int > ans;
for(int i = 1;i <= n;i ++) {
ans.push_back(dp[i]);
}
return ans;
}

B.cpp

#include "B.h"
#include <bits/stdc++.h>
using namespace std;
namespace {
#define MAXN 2005
#define DB double
#define LL long long
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
int n,m,s,o,k;
struct it{
int v,w;it(){v=w=0;}
it(int V,int W){v=V;w=W;}
};
vector<it> g[MAXN];
int dp[MAXN];
int tre[MAXN<<2],M;
int bing(int a,int b) {return dp[a] < dp[b] ? a:b;}
void maketree(int n) {M=1;while(M<n+2)M<<=1;}
void addtree(int x,int y) {
int s = M+x;tre[s] = y; s >>= 1;
while(s) tre[s] = bing(tre[s<<1],tre[s<<1|1]),s >>= 1;
}
int findall() {return tre[1];}
int CNT = 0,ctnm = 0,recnm = 0;
int flag = 0;
void sendnmB(int x,int bt) {
for(int i = bt-1;i >= 0;i --) {
bool tmp = (x & (1<<i));
SendB(tmp);
}return ;
}
int t,las = 0;
void calcu() {
for(int i = 0;i < (int)g[t].size();i ++) {
int y = g[t][i].v,w = g[t][i].w;
if(dp[t] + w < dp[y]) {
dp[y] = dp[t] + w;
addtree(y,y);
}
}
addtree(t,0);
CNT ++;
flag = 1;
t = findall();
if(CNT >= n || !t) {flag = -1;return ;}
sendnmB(min(511,dp[t]-las),9);
return ;
}
}
void ReceiveB(bool x) {
recnm <<= 1;recnm += x;
ctnm ++;
if(flag == 1 && ctnm >= 9) {
if(recnm+las > dp[t]) {
sendnmB(t,11);
las = dp[t];
ctnm = recnm = 0;
calcu();
}
else {
flag = 0;
las = recnm + las;
ctnm = recnm = 0;
}
return ;
}
if(flag == 0 && ctnm >= 11) {
t = recnm;dp[t] = las;
ctnm = recnm = 0;
calcu();
return ;
}
return ;
}
void InitB(int N, int M, vector < int > U, vector < int > V, vector < int > W) {
n = N;m = M;
for(int i = 1;i <= m;i ++) {
s = U[i-1]+1; o = V[i-1]+1; k = W[i-1];
g[s].push_back(it(o,k));
g[o].push_back(it(s,k));
}
maketree(n);
for(int i = 0;i <= n;i ++) dp[i] = 0x7f7f7f7f;
dp[1] = 0;t = 1;las = 0;
calcu();
return ;
}

蕞短鹭(artskjid) (⭐通信题/模拟⭐)的更多相关文章

  1. ACM: NBUT 1105 多连块拼图 - 水题 - 模拟

    NBUT 1105  多连块拼图 Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:  Practice  Appoint ...

  2. Sdut 2409 The Best Seat in ACM Contest(山东省第三届ACM省赛 H 题)(模拟)

    题目描述 Cainiao is a university student who loves ACM contest very much. It is a festival for him once ...

  3. hdu 4706 Children's Day 2013年ICPC热身赛A题 模拟

    题意:按字母顺序排列成n型,简单的模拟题. 当字母排到z时从a开始重新排起. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * Blog: ...

  4. 2019.3.16 noiac的原题模拟赛

    RT,这太谔谔了,我不承认这是模拟赛 但是虽然是搬了三道题,题目本身也还能看,就这么着吧 (怎么机房里就我一道原题都没做过啊 T1 CF24D Broken Robot 比较简单地列出式子之后,我们发 ...

  5. CodeForces 686A Free Ice Cream (水题模拟)

    题意:给定初始数量的冰激凌,然后n个操作,如果是“+”,那么数量就会增加,如果是“-”,如果现有的数量大于等于要减的数量,那么就减掉,如果小于, 那么孩子就会离家.问你最后剩下多少冰激凌,和出走的孩子 ...

  6. CodeForces 342B Xenia and Spies (水题模拟,贪心)

    题意:给定 n 个间谍,m个区间,一个 s,一个f,然后从 s开始传纸条,然后传到 f,然后在每个 t 时间在区间内的不能传,问你最少的时间传过去. 析:这个题,就模拟一下就好,贪心策略,能传就传,找 ...

  7. NOIp2017真题模拟赛 By cellur925

    果然我还是最菜的==不接受反驳 (先考了day2喵喵喵) Day2 T1:奶酪 期望得分:100分 实际得分:100分 考察:并查集 思路:这题其实之前做过了==.思路还是比较清晰的,读入时预处理出可 ...

  8. NOIp 2015真题模拟赛 By cellur925

    果然我还是最菜的==不接受反驳== Day1 T1:神奇的幻方 思路:直接模拟即可,由于当前放法只与上一放法有关系,用两个变量记录一下即可.10分钟内切掉== 预计得分:100分 实际得分:100分 ...

  9. NEFU 2016省赛演练一 I题 (模拟题)

    这题没名字 Problem:I Time Limit:2000ms Memory Limit:65535K Description Now give you an interger m and a s ...

随机推荐

  1. SRE,了解一下?35+岁程序员新选择

    摘要:随着云业务的发展,今后会有越来越多的工程师深入到SRE领域. 本文分享自华为云社区<浅谈SRE角色认知>,作者: SRE确定性运维. 一.什么是SRE? SRE(Site Relia ...

  2. 『忘了再学』Shell基础 — 32、Shell中test测试命令详解

    目录 1.test测试命令 (1)test命令介绍 (2)test命令使用方式 (3)示例 2.按照文件类型进行判断 3.按照文件权限进行判断 4.两个文件之间进行比较 5.两个整数之间比较 6.字符 ...

  3. SmartIDE v0.1.19 - 码云(Gitee)最有价值开源项目奖项、工作区策略、类虚拟机镜像VMLC、Server安装手册

    SmartIDE v0.1.19 (CLI Build 3909, Server Build 3890) 已经发布,本次Sprint主要完成2个重要特性,工作区策略和类虚拟机容器(VM Like Co ...

  4. Maven的安装 和idea的配置

    Maven的安装 和idea的配置 工欲善其事 必先利其器 1 下载maven 官网 下滑 找到Files tar.gz 是linux系统的 .zip window系统 2 maven安装和配置到环境 ...

  5. Linux定时任务--Crond使用教程

    Linux定时任务--Crond使用教程 1. 介绍Crond crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后 ...

  6. [.NET6]使用ML.NET+ONNX预训练模型整活B站经典《华强买瓜》

    最近在看微软开源的机器学习框架ML.NET使用别人的预训练模型(开放神经网络交换格式.onnx)来识别图像,然后逛github发现一个好玩的repo.决定整活一期博客. 首先还是稍微科普一下机器学习相 ...

  7. Django定时任务Django-crontab的使用

    在使用的django做测试平台时,,多多少少都会遇到需要定时任务的功能,比如定时执行任务,检查订单之类 的.可能是一段时间,比如每隔 10分钟执行一次,也可能是定点时间,比如 14:00 执行,也可能 ...

  8. 虚拟机win7系统安装

    win7 x64虚拟机安装步骤 1.点击创建新虚拟机,选择典型 2.选择客户机操作系统:windows 7 x64 3.命名虚拟机 4.指定磁盘容量 5.点击完成 6.编辑此虚拟机设置 7.内存设置 ...

  9. Hadoop - MapReduce 过程

    Hadoop - MapReduce 一.MapReduce设计理念 map--->映射 reduce--->归纳 mapreduce必须构建在hdfs之上的一种大数据离线计算框架 在线: ...

  10. DDL_操作数据库_创建&查询和DDL_操作数据库_修改&删除&使用

    DDL操作数据库.表 1.操作数据库:CRUD C(Create):创建 创建数据库: create database 数据库名称: 创建数据库判断不存在再创建 create database if ...