NOIP2004提高组题解

2023-11-09

T1:津津的储蓄计划

考察知识:模拟

算法难度:X 实现难度:X+

分析:按照题目的要求模拟就可以了,只是要考虑严谨,还要看懂题目

代码:

#include<cstdio>
int cost,rest,store,fail;
int main(){
	for(int i=1;i<=12;i++){
		scanf("%d",&cost);
		rest+=(300-cost);
		if(rest<0) {fail=i;break;}
		else store+=120*(rest/100),rest%=100;
	}
	if(fail) printf("%d\n",-fail);
	else printf("%d\n",store+rest);
	return 0;
}

T2:合并果子

考察知识:二叉堆,模拟,贪心

算法难度:XX 实现难度:XX+

分析:

直接每次合并最小的两堆就可以了

还是那句话:当年不能用STL,所以我们还是按当年的要求来吧(不用优先队列)

用priority_queue很方便,就不贴代码了,下面的代码是用二叉堆实现的,注释里面讲述了使用方法,你需要有二叉树的的知识储备才容易读懂

代码:

#include<cstdio>
#include<algorithm>
const int maxn=10005;
int heap[maxn],np,n,t,sum;//维护一个小根堆
/*heap是储存二叉树的一个数组,2*i,2*i+1是i的
左右儿子,保证这棵二叉树父亲的权值不比儿子大*/ 
void add(int x){//添加元素 
	heap[++np]=x;//把np理解为数组的指针-指向末尾元素
	for(int i=np,j=i/2;j>0;i=j,j/=2){//调整二叉树的节点权值 
		if(heap[j]>heap[i]) std::swap(heap[i],heap[j]);
		else break;
	}
}
void del(){//删除最小元素 
	heap[1]=heap[np--];//把根赋最后节点的值,删除最后节点
	for(int i=1,j=2*i;j<=np;i=j,j*=2){//调整二叉树 
		if(j<np&&heap[j+1]<heap[j]) j++;
		if(heap[i]>heap[j]) std::swap(heap[i],heap[j]);
		else break;
	} 
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&t),add(t);
	while(--n){
		t=heap[1],del();
		t+=heap[1],del();
		add(t),sum+=t;
	}
	printf("%d\n",sum); 
	return 0;
}

T3:合唱队形

考察知识:序列型动态规划

算法难度:XX+ 实现难度:XX+

分析:

其实就是求一次最长上升子序列,然后反着求一次最长下降子序列,然后找最高点就可以了

代码:

#include<cstdio>
#include<algorithm>
int n,a[105],f1[105],f2[105],mx;
//f1(i)=max(f1(j))+1||1<=j<i a[j]<a[i]
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",a+i),f1[i]=f2[i]=1;
	
	for(int i=2;i<=n;i++)
	  for(int j=1;j<i;j++) if(a[j]<a[i])
	    f1[i]=std::max(f1[i],f1[j]+1);
	
	for(int i=n-1;i>=1;i--)
	  for(int j=n;j>i;j--) if(a[i]>a[j])
	    f2[i]=std::max(f2[i],f2[j]+1);
	
	for(int i=1;i<=n;i++) mx=std::max(mx,f1[i]+f2[i]-1);
	printf("%d\n",n-mx);
	return 0;
}

T4:虫食算

考察知识:搜索+剪枝,数学,高斯消元

算法难度:XXXX 实现难度:XXXX

分析:这道题搜索并不难写,但是剪枝的程度决定了你能得多少分

我第一次花了两个小时写(调bug)完了第一份程序,如果不剪枝,时间复杂度为:O(n^2^n),可是我加了剪枝也才20分,然后我修改了一下,时间复杂度开了个根号,然后就可以90分了

下面先介绍90分方法:

首先是命名方式:

add[i]表示第i+1为应该向第i为进一

剪枝:1.如果当前某个字母必须赋某个值而这个值已经被使用,剪枝 2.如果某个字母已经被赋值了,就不用再枚举其可能的值了

其实剪枝并不是很多,也不是很复杂,只不过细节还是很多,很容易写错,情况要分类讨论(我找bug又花了一个小时T_T)

所以忠告大家一定要加强静态查错,考虑每一个可能出错的地方

代码:

#include<iostream>
#include<cstdio>
int n,mp[30],used[30],add[30],got_ans;
char A[30],B[30],C[30];
void dfs(int row,int cur){
    if(row<0){
        if(!add[row+1])//第一位不该有进位 
            for(int i=0;i<n;i++) printf("%d ",mp[i]);
        got_ans=1;return;
    }
    if(got_ans) return;
    int idA=A[row]-'A',idC=C[row]-'A';
    if(cur) goto Cur1;
    //考虑第row列第一行的字母代表的数字: 
    if(mp[idA]>=0) {dfs(row,1);return;}//如果字母已经被赋值 
    for(int i=0;i<n;i++) if(!used[i]){//枚举可以赋的值 
    	mp[idA]=i,used[i]=1;
    	dfs(row,1);
    	mp[idA]=-1,used[i]=0;//修改回原状态 
    }return;
    Cur1://考虑第row列第二行:
    int idB=B[row]-'A';
    if(mp[idB]>=0){//如果字母二已被赋值,分类讨论 
        int t=mp[idA]+mp[idB]+add[row+1];
        add[row]=t/n;//注意进位 
        if(mp[idC]>=0&&t%n==mp[idC]){//如果字母三已被赋值
            dfs(row-1,0);
            add[row]=0;
        }
        else if(mp[idC]<0&&used[t%n]==0){//根据字母一二可以确定字母三 
            mp[idC]=t%n,used[t%n]=1;
            dfs(row-1,0);
            mp[idC]=-1,add[row]=used[t%n]=0;
        }
        return;
    }
    int t;
    for(int i=0;i<n;i++) if(!used[i]){//枚举第字母二可能的值 
        t=mp[idA]+i+add[row+1];
        add[row]=t/n;
        mp[idB]=i,used[i]=1;
        if(mp[idC]>=0&&(t%n==mp[idC])) dfs(row-1,0);
        else if(mp[idC]<0&&used[t%n]==0){
            mp[idC]=t%n,used[t%n]=1;
            dfs(row-1,0);
            mp[idC]=-1,used[t%n]=0;
        }
        mp[idB]=-1,add[row]=used[i]=0;
    }
}
int main(){ 
    scanf("%d%s%s%s",&n,A,B,C);
    for(int i=0;i<n;i++) mp[i]=-1;
    dfs(n-1,0);
    return 0;
}

其实只要再加一个剪枝就是100分算法了:3.考虑剩下的数,如果一列的三个数值都知道了那么就可以判断是否矛盾了

但是要考虑进位(true表示可以剪枝):

bool check(int limt){
	int a,b,c;
	for(int i=0;i<=limt;i++){
		a=mp[A[i]-'A'],b=mp[B[i]-'A'],c=mp[C[i]-'A'];
		//考虑要严谨 
		if(((a+b)%n)!=c&&((a+b+1)%n)!=c&&a>=0&&b>=0&&c>=0) return true; 
	}
	return false;
}

最后修改一下:

    if(got_ans||check(row)) return;

就可以AC了,那个之前超时的点500ms过,还是有点悬,但是比起以前速度快了60多倍

总结:

不知道你有没有注意到所有代码我都没有用using namespace std;

如果你不知道为什么的话——解释:如果因为你不加这句话如果某些地方报错你在它(函数等)前面加  std::  一般就可以了

T1:刚学竞赛一个月就AC了,最近来做没有考虑严谨居然80分T_T

T2:第一次做出现在考试中,那时没有学优先队列,用map做的,100分,现在用二叉堆做,不小心写错一个字母(i写成了j)只得了20分T_T

T4:第一次同时搜索第一行,第二行,超时非常严重(有80分超时),搜索方法略微改变了一下,剪枝没有改就90了(但是找bug花了我很多时间),这说明了什么?:细节,严谨,前瞻性很重要。。。

总之这一年的题我做得非常浮躁,20+80+100+20=220,如果NOIP2018我还这么马虎,我就完了。。。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NOIP2004提高组题解 的相关文章

  • 信息学奥赛一本通(C++版) 刷题 记录

    总目录详见 https blog csdn net mrcrack article details 86501716 信息学奥赛一本通 C 版 刷题 记录 http ybt ssoier cn 8088 http blog csdn net
  • UVA 401 Palindromes 题解

    Palindromes A regular palindrome is a string of numbers or letters that is the same forward as backward For example the
  • 剑指offer—16.数值的整数次方——分析及代码(Java)

    剑指offer 16 数值的整数次方 分析及代码 Java 一 题目 二 分析及代码 1 二分求解 1 思路 2 代码 3 结果 三 其他 一 题目 给定一个 double 类型的浮点数 base 和 int 类型的整数 exponent
  • Pseudoprime numbers(快速幂模板题)

    Fermat s theorem states that for any prime number p and for any integer a gt 1 ap a mod p That is if we raise a to the p
  • G - 数据结构实验之栈与队列七:出栈序列判定

    Description 给一个初始的入栈序列 其次序即为元素的入栈次序 栈顶元素可以随时出栈 每个元素只能入栈依次 输入一个入栈序列 后面依次输入多个序列 请判断这些序列是否为所给入栈序列合法的出栈序列 例如序列1 2 3 4 5是某栈的压
  • C++一行输入多个整数,每个整数用空格隔开,回车结束输入

    C 一行输入多个整数 每个整数用空格隔开 回车结束输入 include
  • POJ 1302 Blue Gene, Jr.(递归实现)

    Inspired by IBM s Blue Gene project the CEO of Universal Biological Machinery UBM has called on you UBM s top software e
  • M个梨子放N个盘子

    M个梨子放N个盘子 题目描述 Macro非常喜欢吃梨 有一天他得到了ACMICPC组委会送给他的一筐梨子 他比较心疼学生 就打算把梨子分给学生吃 现在他要把M个梨子放到N个盘子里面 我们允许有的盘子为空 你能告诉Macro有多少种分法吗 请
  • NOIP2004提高组题解

    T1 津津的储蓄计划 考察知识 模拟 算法难度 X 实现难度 X 分析 按照题目的要求模拟就可以了 只是要考虑严谨 还要看懂题目 代码 include
  • 基于一道ctf 引发的 TP链分析

    回看 newstarctf week 3 的web题 想了想看看tp链吧 这道题是tp5 1 的版本 链比5 0的 短而且清晰 基于我这个shaluan tp不知道为什么动态调试出了问题 就只能静态分析了 首先是定入口 这里5 0和5 1的
  • 【SSL_1232】雷达覆盖

    思路 以一个点作为平角 计算几何统计 c o d e code code include
  • OpenJudge1.4编程基础之逻辑表达式与条件分支

    文章目录 01 判断数正负 02 输出绝对值 03 奇偶数判断 04 奇偶ASCII值判断 05 整数大小比较 06 判断是否为两位数 07 收集瓶盖赢大奖 08 判断一个数能否同时被3和5整除 09 判断能否被3 5 7整除 10 有一门
  • 树的遍历(bfs)

    题目链接 https www acwing com problem content 1499 题目 一个二叉树 树中每个节点的权值互不相同 现在给出它的后序遍历和中序遍历 请你输出它的层序遍历 输入格式 第一行包含整数 N N N 表示二叉
  • CF1512C A-B Palindrome 题解

    题目大意 给定一个字符串 长度为 a b a b a b 给定 a a a
  • POJ - 2531 Network Saboteur

    A university network is composed of N computers System administrators gathered information on the traffic between nodes
  • AcWing题解

    104 货仓选址 417 不高兴的津津 421 陶陶摘苹果 425 明明的随机数 429 奖学金 441 数字统计 445 数字反转 449 质因数分解 680 剪绳子 756 蛇形矩阵 1381 阶乘 3208 Z字形扫描 3375 成绩
  • NOIP题目解析之取石子问题

    题目 现有5堆石子 石子数依次为3 5 7 19 50 甲乙两人轮流从任一堆中取石子 取最后一颗石子的一方获胜 甲先取 请问甲有没有获胜策略 如果有 甲第一步应在哪一堆里取多少 解析 在解这一道题之前 我们可以先来把问题简化 把五堆石子转化
  • NOIP1998普及组复赛第二题 贰的幂方 解题报告

    问题描述 任何一个正整数都可以用 2 的幂次方表示 例如 137 27 23 20 在这里我们约定次方用括号来表示 即 ab 可表示为 a b 由上面叙述可知 137 又可以表示为 2 7 2 3 2 0 进一步 7 22 2 20 2 2
  • 2022第十三届蓝桥杯国赛真题javaB组

    文章目录 试题A 重合次数 试题B 数数 试题C 左移右移 试题D 窗口 试题E 迷宫 试题F 小球称重 试题G 背包与魔法 试题H 修路 试题I 围栏 试题J 好数之和 试题A 重合次数 本题总分 5 分 问题描述 在同一天中 从上午6
  • HDU-7304 2023“钉耙编程”杭电多校赛(3)Out of Control

    2023 钉耙编程 中国大学生算法设计超级联赛 3 Out of Control 题目大意 有 n n n个数 x 1 x

随机推荐

  • Exps on March 25th

    时差 What s your time there What time is it over there 在你那里 现在是几点啊 Greenwich Mean Time GMT 格林威治时间 0时区 伦敦标准时间China is locat
  • 操作系统怎么访问docker内的MySQL

    操作系统怎么访问docker内的MySQL 怎么访问docker内的MySQL 1 获取mysql镜像 docker pull mysql 5 6 2 启动mysql镜像 推荐学习 MySQL视频教程 docker run itd P my
  • 源码阅读心得

    简单记录一下自己最近一段时间阅读一个C语言开源项目的心得 1 阅读工具 source insight 4 0 gdb Typora 2 阅读心得 1 不要陷在代码的实现细节里面出不来 浪费时间 因为稍微大一点的开源项目 都有很多自定义的结构
  • 目标检测之性能指标

    推荐文章 https www cnblogs com isLinXu p 15893489 html
  • 小白循环神经网络RNN LSTM 参数数量 门单元 cell units timestep batch_size

    小白循环神经网络RNN LSTM 参数数量 门单元 cell units timestep batch size RNN循环神经网络 timestep batch size LSTM及参数计算 keras中若干个Cell例如LSTMCell
  • 使用内网穿透实现Blynk服务器远程访问

    使用内网穿透实现Blynk服务器远程访问 使用内网穿透实现Blynk服务器远程访问 1 安装宝塔面板和docker管理器 2 登陆小米球控制台 3 运行小米球linux版本软件 4 手机APP访问和网页访问 5 总结 使用内网穿透实现Bly
  • torch.device

    问题 device torch device cuda if torch cuda is available else cpu AttributeError module object has no attribute device tor
  • linux-basic(12)正则表达式与文件格式化处理

    12 1 1 什么是正则表达式 1 简单说 正则表示法就是处理字串的方法 他是以行为单位来进行字串的处理行为 正则表达式透过一些特殊符号的辅助 可以让使用者轻易的达到查找 删除 替换某特定字串的处理程序 12 1 5 扩展的正则表达式 正则
  • VirtualBox中Ubuntu 14.04 LTS安装GATE7.1

    开发环境 win7 VirtualBox Ubuntu 14 04 LTS 主要参考博客 1 Compilation Instructions V7 1 2 Gate7 1在Ubuntu下编译 3 Package Requirements
  • 面试官:你了解数据安全传输吗?

    鄢栋 微医云服务团队前端工程师 有志成为一名全栈开发工程师甚至架构师 路漫漫 吾求索 生活中通过健身释放压力 思考问题 看到这个标题 很多老铁会斩钉截铁的说 这道题我会 就是用 HTTPS 来进行安全传输的 对 很优秀 那你知道 HTTPS
  • Spring - SpringMVC(一)

    SpringMVC 第一章 SpringMVC入门 补充 浏览器地址中的绝对路径 代表的就是端口后面 哪怕你在配置文件中配置了项目的映射名 也是端口后面 不是映射名后面 它会直接忽视项目的映射名 只代表端口后边 知识点 概述 1 目标 了解
  • 不同数据类型的相关性分析总结

    在进行数据建模之前 我们一般会进行数据探索和描述性分析 发现数据规律及数据之间的相关性 本文主要从检验方法和可视化图形两个方面对不同数据类型的相关性分析方法进行总结 以加强对数据的了解和认识 为建模打下基础 目录 一 不同数据类型的相关性总
  • STL十大容器 之 list

    特点 内存不连续 底层实现是链表 插入和删除的效率比较快 随机访问效率比较低 和vector相比 不再需要 capacity 和 reserve 操作 因为链表没有大小限制 不需要为了效率增加预分配内存的功能 一 插入和删除 push ba
  • vue中从对象数组中拿到每一个对象的其中一个字段作为下拉框的选项

    原因分析 因为是对象数组 所以不能单纯的用this指向来赋值 解决方案 直接上代码 用到ES6的map 方法 具体使用不懂的还请自己百度哦 这是下拉框的代码
  • 记一次网易前端面试

    很幸运地能收到网易的面试通知 就毫不犹豫翘了课去面试了 hhhh 三点的面试 因为从来没去过那个中关村西北旺区 吃完饭早早就去了 想象中那里应该是繁华的地方 hhhh 到了发现都在建设中 很多还在建设中 看到了网易旁边的百度和搜狐 都是长长
  • OpenCV学习笔记——用haar特征训练自己的分类器(再做手势检测)

    之前介绍过一篇利用级联分类器对目标进行检测的文章http blog csdn net yang xian521 article details 6973667 用的就是haar特征 发现OpenCV自带的库里的haar特征只有人脸 人脸的器
  • Spring 中@NotNull, @NotEmpty和@NotBlank之间的区别是什么?

    简述三者区别 NotNull CharSequence Collection Map 和 Array 对象不能是 null 但可以是空集 size 0 NotEmpty CharSequence Collection Map 和 Array
  • 新手学习导航设计的10个技巧

    如果一个网站有良好的可用性 基本的需求是良好的导航设计 本文结合社区优秀的网页导航设计案例 总结了网页导航设计的10项技能 网页导航设计案例即时设计是一款支持在线协作的专业级 UI 设计工具 支持 Sketch Figma XD 格式导入
  • 大学英语词汇解析 中国大学mooc 华中科技大学 测验题答案

    使用方法 利用浏览器的搜索功能 ctrl F and后面为答案 You should practice your scales every day and a set of notes played or sung in order goi
  • NOIP2004提高组题解

    T1 津津的储蓄计划 考察知识 模拟 算法难度 X 实现难度 X 分析 按照题目的要求模拟就可以了 只是要考虑严谨 还要看懂题目 代码 include