写在前面

好久没更新公众号和博客了,因为最近在研究新的方向,所以很少发文。
笔者接触编程只有一年,这一年间主要研究启发式算法在运筹学中的应用。但是由于编程基础薄弱,在进一步研究复杂运筹学问题时发现基础算法不过关导致写出的代码运行速度很慢,因此很苦恼。所以决定这个暑假补习一下基础算法,主要是刷一些简单的ACM入门题。偶尔会发一些刷题笔记(偶尔!)。和作者有类似目标的同学可以一起交流共勉!

目前在看的教程:
北京理工大学ACM冬季培训课程

算法竞赛入门经典/刘汝佳编著.-2版可以在这里下载->github

课程刷题点
Virtual Judge

刷题代码都会放在github上,欢迎一起学习进步!

第二章模拟与暴力刷题点,提交密码20202020

就剩5题了,很难受,就早上写了一下写完先。这次AC比较多哈,除了最后一题没有AC(主要懒的写了呜呜呜)。

K - Coat of Anticubism


cicasso可还行,我还以为自己看错了…

这题应该是数学题…给几条无法组成凸多边形的线段,问新增一条最短长度为多少的线段可以组成凸多边形。其中构成凸多边形时两条线段可以拼接成一条更长的线段(即夹角180°)。

懒得思考数学问题,就直接网上查了一下,发现很多博客题解直接说求三角形,或者语焉不详,我就呵呵。

问题应该就是求三角形,利用两边和大于最长边。但是如何从凸多边形转为三角形呢?思考了一下,类比三角形,凸多边形有这样的性质:最长边小于其他所有边长度之和。(通过划分为多个三角形易证)但是拥有这个性质是否一定能构成凸多边形呢?这个我一下想不出证明,但是我们可以通过拼接线段的方式把这些边拼接成三角形。(不断的把最短的两条边拼成一条边)那么问题就简化为加入一个数,使得除最大数外所有数的和加上这个数 = 原先最大数 + 1。暴力求和即可。

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <string>
#include <set>
using namespace std;typedef long long LL;
#define INT_MAX 0x7fffffff
#define INT_MIN 0x80000000
// #define LOCALint numbers[5000005];
// set<int> num;int main()
{#ifdef LOCALfreopen("data.in", "r", stdin);// freopen("data.out", "w", stdout);
#endifint n;cin >> n;for(int i = 0; i < n; i++)cin >> numbers[i];sort(numbers, numbers + n);int sum = 0;for(int i = 0; i < n - 1; i++)sum += numbers[i];int ans = numbers[n - 1] - sum + 1;cout << ans << endl;return 0;
}

L - Five-In-a-Row


五子棋,判断当前情况某方能否一步内获胜。

棋盘只有10*10,选择之间暴力枚举所有空格位置,判断上下左右斜能否连5颗。

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <string>
#include <set>
using namespace std;typedef long long LL;
#define INT_MAX 0x7fffffff
#define INT_MIN 0x80000000
// #define LOCALint lenth = 10;
char graph[15][15];int main()
{#ifdef LOCALfreopen("data.in", "r", stdin);// freopen("data.out", "w", stdout);
#endiffor (int j = 1; j <= 10; j++)graph[0][j] = 'O'; // 'O'是对面的棋子,等同于代表墙体for (int i = 1; i <= 10; i++){graph[i][0] = 'O';for (int j = 1; j <= 10; j++)graph[i][j] = '.'; // '.'代表空graph[i][10 + 1] = 'O';}for (int j = 1; j <= 10; j++)graph[10 + 1][j] = 'O';for (int i = 1; i <= 10; i++){string str;cin >> str;for (int j = 1; j <= 10; j++)graph[i][j] = str[j - 1];}bool flag = false;for (int i = 1; i <= 10; i++){for (int j = 1; j <= 10; j++){if (graph[i][j] != '.')continue;// 判断左右int left = 0, right = 0;for (int k = 1;; k++){if (graph[i][j - k] == 'X')left++;elsebreak;}for (int k = 1;; k++){if (graph[i][j + k] == 'X')right++;elsebreak;}if ((left + right + 1) > 4){flag = true;goto end;}// 判断上下int up = 0, down = 0;for (int k = 1;; k++){if (graph[i - k][j] == 'X')down++;elsebreak;}for (int k = 1;; k++){if (graph[i + k][j] == 'X')up++;elsebreak;}if ((up + down + 1) > 4){flag = true;goto end;}// 判断左侧斜向上、下up = 0, down = 0;for (int k = 1;; k++){if (graph[i - k][j + k] == 'X')down++;elsebreak;}for (int k = 1;; k++){if (graph[i + k][j - k] == 'X')up++;elsebreak;}if ((up + down + 1) > 4){flag = true;goto end;}// 判断右侧斜向上、下up = 0, down = 0;for (int k = 1;; k++){if (graph[i - k][j - k] == 'X')down++;elsebreak;}for (int k = 1;; k++){if (graph[i + k][j + k] == 'X')up++;elsebreak;}if ((up + down + 1) > 4){flag = true;goto end;}}}end:if (flag)cout << "YES";elsecout << "NO";return 0;
}

M - Island Puzzle


一个循环的队列,其中有一个空位,每次只能向空的位置移动一步,问给出两个队列是否可以相互转换。

去掉空位的0后判断循环是否相等。判断是否相等的时候,可以先找到一个相等的数,再往后判断。

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <string>
#include <set>
#include <queue>
using namespace std;typedef long long LL;
#define INT_MAX 0x7fffffff
#define INT_MIN 0x80000000
//#define LOCALint x[200005];
int y[200005];void swap(int& x, int& y)
{int temp = x;x = y;y = temp;
}int main()
{#ifdef LOCALfreopen("data.in", "r", stdin);// freopen("data.out", "w", stdout);
#endifint n;cin >> n;int m = 0;for (int i = 0; i < n; i++){int temp;cin >> temp;if (!temp)continue;elsex[m++] = temp;}m = 0;for (int i = 0; i < n; i++){int temp;cin >> temp;if (!temp)continue;elsey[m++] = temp;}bool flag = true;int k = 0;while (x[k] != y[0]){k++;}n--;for (int j = 0; j < n; j++){if (x[(k++) % n] != y[j]) {flag = false;break;}}if (flag)cout << "YES";elsecout << "NO";return 0;
}

N - Fractions Again?!


找1/k=1/x+1/y1/k = 1/x + 1/y1/k=1/x+1/y的x和y。

只需要遍历x,设x为较小的数,遍历时从k+1到2k即可。同分之后算y,不然精度可能有问题。

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <string>
#include <set>
#include <math.h>
using namespace std;typedef long long LL;
#define INT_MAX 0x7fffffff
#define INT_MIN 0x80000000
// #define LOCALint main()
{#ifdef LOCALfreopen("data.in", "r", stdin);// freopen("data.out", "w", stdout);
#endifint n;while (cin >> n){int sum = 0;vector<pair<int, int>> num_pair;for (int i = n + 1; i <= 2 * n; i++){if (!(n * i % (i - n))){int j = n * i / (i - n);num_pair.push_back(make_pair(j, i));}}cout << num_pair.size() << endl;for (vector<pair<int, int>>::iterator it = num_pair.begin(); it != num_pair.end(); it++){printf("1/%d = 1/%d + 1/%d\n", n, (*it).first, (*it).second);}}return 0;
}

O - The Answer to the Ultimate Question of Life, The Universe, and Everything.


这个题目比较有意思,题目头就很有意思,做法也很有意思。

给定T∈[0,10]个x,x∈[0,200],分别求满足a3+b3+c3=x的a,b,c,其中a,b,c∈[−5000,5000]。给定T\in[0, 10]个x, x \in [0, 200], 分别求满足a^3 + b^3+c^3 = x的a, b, c, 其中a, b, c \in [-5000, 5000]。给定T∈[0,10]个x,x∈[0,200],分别求满足a3+b3+c3=x的a,b,c,其中a,b,c∈[−5000,5000]。

要遍历两次-5000——5000,这里就已经10e8了,基本超出时间限制。我尝试着写了一下,加了一点优化,比如试了一下预处理立方(可能负优化了),某一个数限定为正数(x > 0),但都不行。看AC的答案发现所有人都是写了一个表:

我感到很吃惊。上网一查才知道,原来打表是一种方法,因为x的范围比较小,直接在本地找出所有x的解然后打表上交。果然神奇。

具体方法可以参考这篇博文,详细介绍了本地打表的代码(有些博文直接写上交的代码,我不知道作者在想些啥):

https://blog.csdn.net/qq_44691917/article/details/103588685

这里就不放我写的了,简单介绍一下博文里的打表思路。

首先200次询问肯定要预处理立方;

算立方根代码里用遍历的方式找三次方,可能效果好一点;

用一个unordered_map,unordered_map是未排序的map,因为内部实现了哈希表,因此查找速度比较快,mark一下下次试试;

肯定有一个正数,因此第一次遍历0-5000;

第二次遍历也可以遍历0-5000,只需要查找的时候查找两次;

下面放下别人的代码(据说138s解决):

#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
typedef long long ll;
tr1::unordered_map<ll,int> f;ll g(ll x){for(ll i=-5000;i<=5000;i++)if (i*i*i==x) return i;}bool find(int x){for(ll i =0;i<=5000;i++)for(long long j=0;j<=5000;j++)if (f.count(i*i*i+j*j*j+x)){printf("a[%d] = %lld;\n",x,g(i*i*i+j*j*j+x));printf("b[%d] = %lld;\n",x,-i);printf("c[%d] = %lld;\n",x,-j);return true;}else if (f.count(i*i*i+j*j*j-x)){//printf("%lld %lld %lld = %d\n",i,j,-g(i*i*i+j*j*j-x),x);printf("a[%d] = %lld;\n",x,g(i*i*i+j*j*j-x)==0?0:-g(i*i*i+j*j*j-x));printf("b[%d] = %lld;\n",x,i);printf("c[%d] = %lld;\n",x,j);return true;}return false;
}int main()
{freopen("ans.txt","w",stdout);f.clear();for(ll i=-5000;i<=5000;i++)f[i*i*i] = 1;for(int x=0;x<=200;x++){//printf("find %d\n",x );if (find(x)){printf("vis[%d] = true;\n",x);}elseprintf("vis[%d] = false;\n",x);}return 0;
}

结语

模拟暴力结束了…然而紫书里还有一章讲模拟暴力…紫书难度比较大,感觉比这个要难,我决定紫书还是慢慢刷吧…下次把紫书上的STL部分刷一点先。

算法入门刷题笔记 Day2 K - Coat of Anticubism L - Five-In-a-Row M - Island Puzzl......相关推荐

  1. 算法入门刷题笔记 Day10 - A - 拓扑排序·一 -- D - K-th Path

    写在前面 好久没更新公众号和博客了,因为最近在研究新的方向,所以很少发文. 笔者接触编程只有一年,这一年间主要研究启发式算法在运筹学中的应用.但是由于编程基础薄弱,在进一步研究复杂运筹学问题时发现基础 ...

  2. 图解算法数据结构刷题笔记02

    系列文章目录 图解算法数据结构刷题笔记01 本篇文章目录 系列文章目录 前言 1.剑指 Offer 05. 替换空格 2.剑指 Offer 06. 从尾到头打印链表 3.剑指 Offer 09. 用两 ...

  3. 如何判断链表中是否存在环?Floyd判圈算法 leetcode刷题笔记 142. 环形链表 II

    这道题使用了floyd判圈算法,所以先讲解floyd算法的原理和实现,最后在附加上第142题的代码. floyd算法: 一.用途: 可以在有限状态机.迭代函数或者链表上判断是否存在环,求出该环的起点与 ...

  4. 基础夯实,字节内部总结240道算法LeetCode刷题笔记,直呼太全

    1.什么是算法 算法(algorithm,[ˈælɡərɪðəm],计算程序):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出.简单来说算法就是一系列的计算步骤,用来将 ...

  5. LeetCode《算法入门》刷题笔记(31 题全)

    LeetCode<算法入门>刷题笔记(31 题全) 二分查找 1. 二分查找 _解法1:二分搜索(迭代) 解法2:二分搜索(递归) 2. 第一个错误的版本 _解法1:二分 3. 搜索插入位 ...

  6. Github最强算法刷题笔记.pdf

    资料一 昨晚逛GitHub,无意中看到一位大佬(https://github.com/halfrost)的算法刷题笔记,感觉发现了宝藏!有些小伙伴可能已经发现了,但咱这里还是忍不住安利一波,怕有些小伙 ...

  7. LeetCode《编程能力入门》刷题笔记(34 题全)

    LeetCode<编程能力入门>刷题笔记 基本数据类型 1. 在区间范围内统计奇数数目 _解法1:暴力迭代 _解法2:数学(找规律) 2. 去掉最低工资和最高工资后的工资平均值 _解法1: ...

  8. 生物信息学算法之Python实现|Rosalind刷题笔记:003 中心法则:翻译

    我在生物信息学:全景一文中,阐述了生物信息学的应用领域非常广泛.但是有一点是很关键的,就是细胞内的生命活动都遵从中心法则,生物信息学很多时候就是在中心法则上做文章: 分子生物学中心法则:DNA --& ...

  9. 《动态规划入门》刷题笔记(更新中)

    <动态规划>刷题笔记 1. 斐波那契数 2. 第 N 个泰波那契数 3. 爬楼梯 4. 使用最小花费爬楼梯 5. 打家劫舍 6. 打家劫舍 II 7. 删除并获得点数 8. 跳跃游戏 9. ...

最新文章

  1. mysql 主从复制 性能_zabbix监控mysql各项性能,主从复制
  2. 遮挡人脸检测--Detecting Masked Faces in the Wild with LLE-CNNs
  3. 编程语言python特点-Python语言的特点有哪些?九大特点介绍!
  4. Action访问Servlet API的三种方法
  5. 图像处理理论(七)——LBP, Fisherface, Viola-Jones
  6. 服务器能否只做c盘系统,我的云服务器只有一个c盘
  7. “这辈子不可能打工男子”出狱了,司法所将重点关注,网友:《今瓶没》今日上映!...
  8. 解决 Beyond Compare 3 许可证密钥被撤销
  9. 准备在北京Tech·Ed上组织博客园聚会
  10. Java架构-CAS SSO单点登录框架介绍
  11. matlab mysvd代码解释,关于使用SVD进行PCA主成分提取的代码问题!也是必须涉及到原理的!...
  12. warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory
  13. Java 线程池学习
  14. Oracle 单实例 迁移到 RAC 实例 -- 使用导出导入方法
  15. BLM战略规划的核心是业务模式创新
  16. 中兴b860修改mac_【原创】猫盘群晖超级简单修改【SN MAC】 工具
  17. 如何简单快速的写出幸运转盘抽奖
  18. jsp网页在线编辑器
  19. CSS3初级学习(二)背景图片叠加
  20. 基于树莓派的手势识别Oled屏幕显示

热门文章

  1. Python 中的 defaultdict 数据类型
  2. Windows安装Redis5.x
  3. matlab diag函数生成矩阵,Matlab矩阵运算函数-blkdiag函数
  4. 利用 element ui 进度条实现渐变 条纹进度条
  5. can和could的用法_could的用法
  6. tplink无线桥接WDS小结
  7. vscode快速注释代码
  8. 各代iphone尺寸_历代16款iPhone厚度对比:最薄的竟是iPhone 6!
  9. 2020电脑配置基本知识入门,电脑配置知识大全2020
  10. linux动态磁盘怎么转换,动态磁盘转换器【使用办法】