NOIP2010提高组复赛 解题报告(C/C++)(机械翻译)(乌龟棋)(关押罪犯)(引水入城)

本文主要是介绍NOIP2010提高组复赛 解题报告(C/C++)(机械翻译)(乌龟棋)(关押罪犯)(引水入城),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2017.2.18日的练习赛(NOIP2010)

作为一个OI届的晚辈,能接触到近七年前的NOIP考试无疑是一件令人兴奋的事情。这倒不是因为什么信仰,实在是因为只有一试四道题(而不是二试六道题),做起来让人没有“后顾”之忧。下面我们来看看:

1.机械翻译


解题报告:
不得不说,这道题作为第一题是非常“温柔”的。众所周知,“模拟”算法(如果能称作一个算法的话)是NOIP最常考的考点(没有之一)。这道题就是对一个数据结构“队列”进行模拟。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=1005;
int n,m,tot=0;
int head=1,tail=0,queue[N];//head头指针、tail尾指针、queue队列(用数组模拟)
int main()
{freopen("translate.in","r",stdin);freopen("translate.out","w",stdout);memset(queue,0,sizeof(queue));scanf("%d%d",&n,&m);while(m--){int t;scanf("%d",&t);for(int i=head;i<=tail;i++)if(queue[i]==t)goto h;tot++;queue[++tail]=t;if(tail-head+1>n)head++;//内存占满的情况h:;}printf("%d",tot);return 0;
}

2.乌龟棋

解题报告:
这里写图片描述
看到这道题我就闻到了浓浓的动态规划的味道。众所周知,动态规划作为NOIP第二“关心”的考点,是不可能不会见到的(但是,囿于姿势水平太低,一开始是用dfs暴力做的(加上一点点剪枝))。这道题dp的思路是这样的:
先统计出走一步、两步、三步、四步的牌的个数。然后通过四个循环枚举每一种情况,这样来dp。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=355;
const int M=125;
const int P=45;
int n,m;
int f[P][P][P][P],card[5],map[N];//f数组来dp,card数组来存储四种牌的个数、map来记录每一个点的点权。
int main()
{memset(card,0,sizeof(card));freopen("tortoise.in","r",stdin);freopen("tortoise.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&map[i]);for(int i=1;i<=m;i++){int x;scanf("%d",&x);card[x]++;}f[0][0][0][0]=map[1];//赋f数组的第一个初值。for(int i=0;i<=card[1];i++)for(int j=0;j<=card[2];j++)for(int k=0;k<=card[3];k++)for(int l=0;l<=card[4];l++)//dp过程{int loc=i+j*2+k*3+l*4+1;if(i)f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]+map[loc]);if(j)f[i][j][k][l]=max(f[i][j][k][l],f[i][j-1][k][l]+map[loc]);if(k)f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k-1][l]+map[loc]);if(l)f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k][l-1]+map[loc]);}printf("%d",f[card[1]][card[2]][card[3]][card[4]]);return 0;
}

3.关押罪犯

这里写图片描述
解题报告:
这里可以把两个罪犯是否有关联抽象成一幅图,那么我们知道,图是用临界表存储的。这里就解决了存储问题。
此外,我们还需要用到并查集的思想,记录哪两个犯人不在一个监狱里面。如果我们把临界表按路权排好序(从小到大)过后,在不断放入的过程中,要是我们找到目前的一对已经被“安排”过了,就输出。不然的话,我们就将两个分别与对方的“镜像”安排在一起。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int M=100005;
const int N=40005;
struct edge
{int u,w,v,next;edge(){next=-1; }
};
struct edge ed[M];
int num=0;
int head[N];
int father[2*N];
int n,m;
void build(int u,int v,int w)
{++num;ed[num].u=u;ed[num].v=v;ed[num].w=w;ed[num].next=head[u];head[u]=num;
}
bool cmp(const edge &a,const edge &b)
{return a.w>b.w;
}
int getfather(int x)//并查集
{return father[x]==x?x:getfather(father[x]);
}
int main()
{freopen("prison.in","r",stdin);freopen("prison.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);build(u,v,w);}for(int i=1;i<=2*n;i++)father[i]=i;sort(ed+1,ed+m+1,cmp);for(int i=1;i<=m;i++){int u=ed[i].u,v=ed[i].v;if(getfather(u)==getfather(v))//“被安排”过了{printf("%d",ed[i].w);return 0;}father[getfather(v)]=getfather(ed[i].u+n);//“安排”一对罪犯。father[getfather(u)]=getfather(ed[i].v+n);}printf("0");return 0;
}

4.引水入城

这里写图片描述
解题报告:
这道题我们将湖泊边的每一个城市能够在沙漠边“覆盖”到的区域弄成一个线段(这个通过深搜来实现),再通过简单的小dp(或者贪心也可以)来选择哪几座靠湖的城市最优(区间dp,线段覆盖)。需要注意的是,我们为了判定能否满足要求(是否需要输出0),可以通过一个广搜来判特。

#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int N=500;
int dir[5][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct loc
{int x,y;
};
struct loc queue[N*N];
struct s
{int l,r;
};
struct s seg[N];
int map[N+5][N+5],f[N+5];
int flag[N+5][N+5];
int n,m;
int now,rest; 
void bfs()//广搜来判断是否能到 
{int head=0,tail=0;for(int i=1;i<=m;i++){flag[1][i]=1;queue[++tail].y=i;queue[tail].x=1;}do{head++;for(int i=0;i<=3;i++){int x=queue[head].x+dir[i][0],y=queue[head].y+dir[i][1];if(x>n&&x<1&&y>n&&y<1)continue;if(map[x][y]>map[queue[head].x][queue[head].y])continue;if(flag[x][y]==1)continue;queue[++tail].x=x;queue[++tail].y=y;flag[x][y]=1;}}while(head<tail);
}
void dfs(int x,int y)//深搜来更新能覆盖到的线段
{if(x==n){seg[now].l=min(seg[now].l,y);seg[now].r=max(seg[now].r,y);}for(int i=0;i<=3;i++){int x1=x+dir[i][0],y1=y+dir[i][1];if(x1>n&&x1<1&&y1>n&&y1<1)continue;if(map[x1][y1]>map[x][y])continue;if(flag[x1][y1]==1)continue;flag[x1][y1]=1;dfs(x1,y1);flag[x1][y1]=0;}
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&map[i][j]);bfs();//判特for(int i=1;i<=m;i++)if(!flag[1][i])rest++;if(rest)printf("0\n%d",rest);//判特printf("1\n");for(int i=1;i<=m;i++){memset(flag,0,sizeof(flag));now=i;seg[now].l=m+1;seg[now].r=0;flag[1][i]=1;dfs(1,i);}f[0]=0;for(int i=1;i<=m;i++){f[i]=0x7fffffff;for(int j=1;j<=m;j++)if(i>=seg[j].l&&i<=seg[j].r)f[i]=min(f[i],f[seg[j].l-1]+1);}printf("%d",f[m]);return 0;
}

以上
2017.2.22

这篇关于NOIP2010提高组复赛 解题报告(C/C++)(机械翻译)(乌龟棋)(关押罪犯)(引水入城)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/855950

相关文章

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

uva 10154 DP 叠乌龟

题意: 给你几只乌龟,每只乌龟有自身的重量和力量。 每只乌龟的力量可以承受自身体重和在其上的几只乌龟的体重和内。 问最多能叠放几只乌龟。 解析: 先将乌龟按力量从小到大排列。 然后dp的时候从前往后叠,状态转移方程: dp[i][j] = dp[i - 1][j];if (dp[i - 1][j - 1] != inf && dp[i - 1][j - 1] <= t[i]

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝