1.数字游戏

算法分析

共8个字符,可以用循环读入,也可以用scanfscanfscanf一次性读入。然后判断计数。

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
int main()
{char c;int num = 0;for (int i = 1; i <= 8; ++i){cin>>c;if (c == '1') ++num;}cout<<num<<endl;
}

2.公交换乘

算法分析

依次读入。判断是地铁的话,结果累加,然后将该地铁的信息放进队列中,队列用数组维护即可。判断是公交车的话,首先维护队首,让超出时间范围的地铁票出队,然后在队列中寻找票价大于当前的公交车票价的地铁票。使用过的地铁票要标记。每次是公交车的时候,最多在45个地铁中选,时间复杂度最坏情况下为O(45n)O(45n)O(45n)。

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
int q[100010], l = 1, r;
int vis[100010];
struct node
{int price, t;
}a[100010];
int main()
{int ans = 0;int n; scanf("%d", &n);int stype, sprice, st;for (int i = 1; i <= n; ++i){scanf("%d%d%d", &stype, &sprice, &st);if (stype == 0){ans += sprice;a[i].price = sprice; a[i].t = st;q[++r] = i;}else{while (l <= r && st - a[ q[l] ].t > 45) ++l;int ok = 0;for (int j = l; j <= r; ++j)if (a[ q[j] ].price >= sprice && vis[j] == 0){vis[j] = 1;ok = 1;break;}if (!ok) ans += sprice;}}printf("%d\n", ans);return 0;
}

算法拓展

用队列维护地铁票的信息,因为最优决策不具有单调性,所以还需要标记,有个更简便的办法,改用双向链表去维护地铁票的信息,可以做到O(1)O(1)O(1)删除。数组模拟双向链表。每个地铁票只会被访问一次,整体时间复杂度O(n)O(n)O(n)。

3.纪念品

算法分析

每天每件纪念品可以被买和卖无限次,相当于在每天的第一时刻,把所有纪念品卖掉换成钱,然后当天后面纯是买的动作。在同一天内买卖纪念品不能赚取差价,当天买第二天卖才可能赚取差价,每个纪念品可以被无限次买,即纪念品的数量是无穷的。问题转化为:

在每一天的开始,有mmm元钱,有nnn个纪念品,每个纪念品有无穷多个,第iii个纪念品有体积为price[i]price[i]price[i],即它的价格,价值为第二天的价格和当天的价格之差,可正可负。完全背包模型。

f[i][j]:f[i][j]:f[i][j]:规划到第iii个物品,目前手里的钱有jjj元,将买来的纪念品第二天都卖掉,所能获得的最大收益。

f[i][j]=max(f[i−1][j],f[i][j+p[k][i]]−p[k][i]+p[k+1][i])f[i][j] = max(f[i-1][j], f[i][\,j + p[k][i]\,] - p[k][i] + p[k+1][i])f[i][j]=max(f[i−1][j],f[i][j+p[k][i]]−p[k][i]+p[k+1][i])

p[k][i]p[k][i]p[k][i]表示第kkk天第iii个纪念品的价格。

等号左侧的jjj要小于右侧的j+p[k][i]j + p[k][i]j+p[k][i],因此要逆序循环体积。f[i][j+p[k][i]]f[i][\,j + p[k][i]\,]f[i][j+p[k][i]]此时也表示是本行的状态,符合完全背包模型。

注意边界处理。f[i][m]f[i][m]f[i][m]表示手里有mmm元钱的最大收益,此时手里的钱没花,因此第二天也不会有收益,赋值为mmm。可将f[0][m]=mf[0][m] = mf[0][m]=m作为边界,以后会自动赋值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include <cmath>
using namespace std;
int T, n, m, p[110][110], f[110][10010];
int main()
{scanf("%d%d%d", &T, &n, &m);for (int i = 1; i <= T; ++i) for (int j = 1; j <= n; ++j) scanf("%d", &p[i][j]); // f[i][j]:规划到第i个物品,手里还剩j元钱,第二天把物品都卖掉的总收益  for (int k = 1; k < T; ++k){for (int i = 0; i <= 10000; ++i) m = max(m, f[n][i]);memset(f, 0xcf, sizeof(f)); f[0][m] = m;  // 边界  for (int i = 1; i <= n; ++i){      for (int j = m; j >= 0; --j)if (j <= m - p[k][i]) f[i][j] = max(f[i-1][j], f[i][j + p[k][i]] - p[k][i] + p[k+1][i]);   // 取或不取 else f[i][j] = f[i-1][j];  // 不取  }}for (int i = 0; i <= 10000; ++i) m = max(m, f[n][i]);printf("%d\n", m);return 0;
}

算法拓展

1.对于买和卖这种交叉在一起的过程,就要考虑能不能过程转化。转化,是将复杂问题简单化的方式。在数据规模中提到,金币数不可能超过10410^4104,像这种字眼,就该考虑入维度了,或者hashhashhash思想。题面是不会给多余的信息的。

2.完全背包可以优化掉一个维度。

for (int k = 1; k < T; ++k)
{for (int i = 0; i <= 10000; ++i) m = max(m, f[i]);memset(f, 0xcf, sizeof(f)); f[m] = m;  // 边界  for (int i = 1; i <= n; ++i){      for (int j = m - p[k][i]; j >= 0; --j)f[j] = max(f[j], f[j + p[k][i]] - p[k][i] + p[k+1][i]);   // 取或不取 }
}

4.加工零件

算法分析

看描述,应知是图论模型。nnn个点mmm条边的无向非连通图。一个点完成的任务为000,则是需要提供原材料。查询的时候,如果aaa点和1号点不连通,结果是“No”。我们讨论下连通时的情况,aaa点要完成的任务是LLL。

假设L=7L=7L=7,aaa点距离1的距离是3,则aaa点可以通过“跳过去再跳过来”的方式消耗掉2的倍数,aaa点可以完成为3的零件。此时,可以推出1号点完成的任务为0,需要提供原材料。如果aaa点距离1的距离是4,aaa点通过以上方式消耗,可以完成为5的零件,倒推到1号点的时候,1号点可以完成为1的零件。这种情况下,也是“No”。同样可以枚举L=6L=6L=6,距离为3和4的情况。可以得出,在处理aaa点到1号点的距离时分奇偶。

如果LLL为奇数,距离为奇数且小于等于LLL,则为“Yes”,否则为“No”。如果LLL为偶数,距离为偶数且小于等于LLL,则为“Yes”,否则为“No”。

aaa点距离1号点的路径也许并非一条,尤其是有环的情况下,不同路径会更多。路径长度有奇数也会有偶数。思考发现,只需要最短奇数路径长度和最短偶数路径长度。设dis1[i]dis1[i]dis1[i]表示1到iii号点的偶数最短路,dis2[i]dis2[i]dis2[i]表示1到iii号点的奇数最短路。对于起点1,只存在偶数最短路,dis1[1]=0dis1[1] = 0dis1[1]=0。其余初始化为正无穷。用dij + 堆优化、bfs或spfa都可以。现在转化为了最短路问题。

对于u−>vu->vu−>v,如果dis1[u]dis1[u]dis1[u]存在,则dis2[v]=dis1[u]+1dis2[v] = dis1[u] + 1dis2[v]=dis1[u]+1。如果dis2[u]dis2[u]dis2[u]存在,则dis1[v]=dis2[u]+1dis1[v] = dis2[u] + 1dis1[v]=dis2[u]+1。

#include<iostream>
#include<cstdio>
#include<cstring>
#include <cmath>
#include <queue>
using namespace std;
int n, m, q, cnt, h[100010];
int dis1[100010], dis2[100010];  // dis1:偶数最短路,dis2:奇数最短路
struct node
{int next, to;
}edg[200010];
queue<int> sq;
void sadd(int u, int v)
{++cnt;edg[cnt].next = h[u];edg[cnt].to = v;h[u] = cnt;
}
void spfa()
{dis1[1] = 0; sq.push(1); while (sq.size()){int u = sq.front(); sq.pop(); for (int i = h[u]; i; i = edg[i].next){int v = edg[i].to;if (dis1[u] != 0x3f3f3f3f){if (dis2[v] > dis1[u] + 1){dis2[v] = dis1[u] + 1;sq.push(v); }}if (dis2[u] != 0x3f3f3f3f){if (dis1[v] > dis2[u] + 1){dis1[v] = dis2[u] + 1;sq.push(v); }}}}
}
int main()
{scanf("%d%d%d", &n, &m, &q);int x, y;for (int i = 1; i <= m; ++i){scanf("%d%d", &x, &y);sadd(x, y); sadd(y, x);}memset(dis1, 0x3f, sizeof(dis1));memset(dis2, 0x3f, sizeof(dis2));spfa();while (q--){int a, l; scanf("%d%d", &a, &l);if (a == 1 && h[a] == 0) printf("No\n"); // a是孤立点  else if (dis1[a] == 0x3f3f3f3f && dis2[a] == 0x3f3f3f3f) printf("No\n");  // a和1不连通  else{if (l % 2) // 奇数  {if (dis2[a] <= l) printf("Yes\n"); else printf("No\n"); }else{if (dis1[a] <= l) printf("Yes\n"); else printf("No\n");}}}return 0;
}

算法拓展

1.dij + 堆优化。边权可看作是1,非负,可以用迪杰斯特拉。

2.边权全都是1,可以直接用bfs搜,第一次到的点就是最短路。bfs的复杂度是O(n)O(n)O(n)。bfs求最短路一般适用于两种情况,边权全为1和边权只能为1或0。前者用普通队列,后者用双端队列,每次为0的时候,从队头入队,为1的时候从队尾入队。

3.分层图。分层图多用于求最短路径,但是最短路径中可以有k条边的权值为0,或者加了其他的附加条件。

分层图的构建步骤为:
(1)先将图复制k+1份。
(2)对于图中的每一条边<u, v>,从u到vi+1v_{i+1}vi+1​连边,ui+1u_{i+1}ui+1​到v连边。

然后在整张图上跑相应图论算法。

博客学习分层图

练习题目:飞行路线

分层图有变形应用。对于本题来讲,每层之间的点不连边,第1层和第2层之间的点连边。1号点能到达的第2层的点之间一定是奇数长度,到达的第1层的点一定是偶数长度。如果到达不了,说明没有对应的奇偶长度。以下图为例:


建立分层图后为:


4、5、6三个点是第2层的点。1号点到不了2号点,说明1和2之间没有偶数路径。从1号点开始跑最短路即可。这里用的是dij+堆优化。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <utility>
#define ll long long
using namespace std;
struct node
{int next, to;
}edg[400010];
int cnt, h[200010];
void sadd(int u, int v)
{++cnt;edg[cnt].next = h[u];edg[cnt].to = v;h[u] = cnt;
}
int dis[200010], vis[200010];
queue<pair<int, int> > sq; // 大根堆
int main()  // 分层图
{int n, m, q;scanf("%d%d%d", &n, &m, &q);int u, v;for (int i = 1; i <= m; ++i){scanf("%d%d", &u, &v);sadd(u, v + n);sadd(v + n, u);sadd(u + n, v);sadd(v, u + n);}memset(dis, 0x3f, sizeof(dis));sq.push(make_pair(0, 1));dis[1] = 0; while (sq.size()){u = sq.front().second; sq.pop();if (vis[u]) continue;vis[u] = 1;for (int i = h[u]; i; i = edg[i].next){v = edg[i].to;if (dis[v] > dis[u] + 1){dis[v] = dis[u] + 1;sq.push(make_pair(-dis[v], v));}}}// dis[i]:1到i的偶数最短路, dis[i+n]:1到i的奇数最短路  int a, L;while (q--){scanf("%d%d", &a, &L);if (L % 2) {if (dis[a+n] <= L) printf("Yes\n"); else printf("No\n");}else {if (dis[a] <= L) printf("Yes\n"); else printf("No\n");}}return 0;
}

4.记忆化搜索。有人用此法得了80分。暴力算法也是应该苦练的。

博客链接

下面是别人的代码:

用rec[u][l]表示工人u加工l阶段是否需要编号为1的人提供原料
需要:rec[u][l]=1;不需要rec[u][l]=-1;不确定:rec[u][l]=0;

#include<bits/stdc++.h>
#define r register
using namespace std;int read(){int res=0,f=1;char ch;while(isspace(ch=getchar()));if(ch=='-') f=-1,ch=getchar();do{res=res*10+ch-'0';}while(isdigit(ch=getchar()));return res*f;
}const int maxn=2e4;
int cnt,n,m,q,sure,cntmt;
int head[maxn],rec[maxn][maxn],xfkmt[maxn],yfkmt[maxn];
bool vis[maxn][maxn];struct edge{int u,v,next;
}e[maxn];inline void adde(int x,int y){e[++cnt].u=x;e[cnt].v=y;e[cnt].next=head[x];head[x]=cnt;
}void dfs(int now,int depth){if(sure==1) return;if(rec[now][depth]==-1||vis[now][depth]) return;if(rec[now][depth]==1){sure=1;return;}if(depth==1) {for(r int i=head[now];i;i=e[i].next)if(e[i].v==1){sure=1;break;} if(sure!=1) rec[now][depth]=-1; return; }for(r int i=head[now];i;i=e[i].next){dfs(e[i].v,depth-1);vis[e[i].v][depth-1]=1;++cntmt;xfkmt[cntmt]=e[i].v;yfkmt[cntmt]=depth-1;}
}int main(){   n=read(),m=read(),q=read();int u,v;for(r int i=1;i<=m;i++){u=read(),v=read();adde(u,v);adde(v,u); }int l;for(r int k=1;k<=q;k++){u=read(),l=read();cntmt=0;sure=-1;dfs(u,l);   if(sure==1) printf("Yes\n");else printf("No\n");rec[u][l]=sure;for(r int i=1;i<=cntmt;i++)vis[xfkmt[i]][yfkmt[i]]=!vis[xfkmt[i]][yfkmt[i]];}return 0;
}

CSP-J2019第二轮 解题分析相关推荐

  1. CSP-J2021第二轮 解题分析

    1.分糖果 算法分析 糖果总数k属于 [ l , r ] [l, r] [l,r],其中 l > = n l >= n l>=n,每个小朋友最少会分到 ⌊ l / n ⌋ \lflo ...

  2. 考公第二轮 | 资料分析

    教程 公众号:公考齐麟 [资料自学视频课程]第一节:资料分析基本公式 公式必须是条件反射,不能有任何的思考,脱口而出 3.增长量识别与强化练习题 6.(图片版)资料分析 必备(背)公式 [资料自学视频 ...

  3. 【百度之星2014~初赛(第二轮)解题报告】JZP Set

    声明 笔者近期意外的发现 笔者的个人站点 http://tiankonguse.com/ 的非常多文章被其他站点转载,可是转载时未声明文章来源或參考自 http://tiankonguse.com/  ...

  4. 2019第十四届全国菌根学术研讨会(第二轮通知)

    文章目录 2019第十四届全国菌根学术研讨会(第二轮通知) 猜你喜欢 写在后面 2019第十四届全国菌根学术研讨会(第二轮通知) 菌根是植物与菌根真菌形成的互惠共生体,是土壤-微生物-植物的生命热区, ...

  5. 下载银海浏览器_【教师研培】停课不停学 停课不停研 ——记银海学校全体英语教师参加市教科院“超越时空 传递智慧”第二轮教研直播活动...

    停课不停学 停课不停研 --记银海学校全体英语教师参加市教科院"超越时空 传递智慧"第二轮教研直播活动 此次带来线上讲座的共有三位专家,首先是株洲市教科院易老师带来的<小学英 ...

  6. POJ 1002 解题分析

    Technorati 标签: ACM,POJ 题目描述 题目链接 POJ 1002 487-3279 Time Limit: 2000MS Memory Limit: 65536K Total Sub ...

  7. 精化集ASP.NET AJAX与ASP.NET MVC分类第二轮筛选结果

    以下是包同学导给我的清单.老赵的第二轮把关很严,杀了几乎99%的文章.不过似乎有少部分并没有经过我的手,可能是其他同学转过来的吧.第三轮老赵依旧会严格把关,肯定也会杀更多(包括通过其他同学第二轮的)文 ...

  8. .net 遍历数组找重复值写入一个新数组_第二轮 Python 刷题笔记一:数组

    经过四十多天缓慢的刷题,现在进度大概是刷了八十多道 LeetCode 题,最近也在吸取过来人的经验,仍然需要对刷题计划进行调整. 首先明确一下目标,我是有些 Python 基础,想通过刷题掌握更多算法 ...

  9. PMP第二轮复习:整本书内容融会贯通

    PMP第二轮复习:整本书内容融会贯通 启动 首先接触制定项目章程,确立项目地位,授权项目经理动用组织资源,高层级信息. 商业论证:项目为啥值得投资,效益管理计划,外部项目签订协议(合同),组织过程资产 ...

最新文章

  1. linux 查看域名解析,linux查询服务器域名解析记录
  2. 20个开源项目助你快速掌握区块链应用开发,JS Go PHP Python Ruby
  3. idea刷新项目、清除项目缓存
  4. Hadoop 之父:普通程序员到顶级公司 CTO 的进阶之路
  5. python之高级的文件操作shutil模块
  6. 计算机语言 时间,甲骨文将ISO日期到计算机的语言环境日期/时间
  7. JZOJ 100024. 【NOIP2016提高A组模拟7.6】数球
  8. log4j:WARN No appenders could be found for logger ().解决方案
  9. vue +element 导出多级表头(标题)
  10. Mac使用minicom串口工具
  11. 计算机初级技能词,计算机领域英语常用词汇初级.doc
  12. Microsoft Visual Studio .NET 2003 编译xvidcore-1.1.3
  13. 除了定时器,真的没法在Simulation Node 类型的CAPL节点中实现延时了吗?
  14. 宗海图cad_技术绘制论文,关于CAD技术机械制图关键技术相关参考文献资料-免费论文范文...
  15. 【树莓派】在Raspbian下将wifi中继为有线网络
  16. M1系列Mac用U盘如何重装系统
  17. Java零基础学习-API每日单词(日更)
  18. 转化Foggy_Cityscapes数据集为voc和yolo格式用作目标检测
  19. 求学信计算机专业英语,求学信模板英文
  20. html的空格代码怎么写?教你如何使用空格nbsp代码(收藏)

热门文章

  1. ib中文文学课如何学习重点?
  2. Blinn-Phong反射模型
  3. 注意2022年软考网络规划设计师考试新版大纲和教程已出炉
  4. 使用代理服务器打不开网页_导致网站打不开的原因有哪些
  5. Android (嘤)英语语音识别 简单概况
  6. 辽宁小学计算机课本,辽宁初中教材版本
  7. 单片机寻迹小车ppt_基于单片机循迹小车的设计.doc
  8. Carrying Conundrum CodeForces - 1567C
  9. 2万字带你了解Selenium全攻略
  10. 奥巴马当选总统之芝加哥演讲全文及…