前言
本文所提及的部分题目代码,可以在我的Github上找到
第一部分 经验分享及感受
第二部分 刷题记录
一、基础算法&程序语言
//strlen()函数的复杂度是O(n)要小心
//截取字符串
strncpy(char* ch,const char* pos,size_t len);
char s[100];
char *p;
strncpy(p,s+10,3);//这个函数不会自动加’\0’
C++ string类
//string反转,需包含头文件<algorithmn>
reverse(s.begin(),s.end());
/*
string和int类型互转,需包含头文件<sstream>和<string>
*/
void str2int(int &int_temp,const string &string_temp)
{
stringstream stream(string_temp);
stream>>int_temp;
}
void int2str(const int &int_temp,string &string_temp)
{
stringstream stream;
stream<<int_temp;
//此处也可以用 stream>>string_temp
string_temp=stream.str();
}
//任意数值类型的模板函数
template <class T>
T stringToNum(string& str)
{
istringstream iss(str);
T num;
iss >> num;
return num;
}
template<class T>
string numtoString(const T& t){
//创建一个格式化输出流
ostringstream oss;
//把值传递如流中
oss<<t;
return oss.str();
}
//读入一行
string s;
getline(cin,s);
//读入直到空格(不包括空格)
string s;
cin>>s;
/*
读入直到指定字符ch,这里ch不会被读入到s中,而且好像也不会存在于缓冲区中
*/
string s;
getline(cin,s,ch);//第3个参数省略时默认为'\n'
//字符串截取
string s;
//注意第2个参数是截取的长度而不是结束的下标
s.substr(s,len);
new&delete
创建并释放一维数组
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
//分配动态一维数组
int *arr=new int[n];
for(int i=0;i<n;i++)
cin>>arr[i];
for(int i=0;i<n;i++)
cout<<arr[i]<<" ";
//释放arr数组
delete[] arr;
return 0;
}
创建并释放二维数组
#include<iostream>
using namespace std;
int main()
{
int row,col;
cin>>row>>col;
//为行指针分配空间
int **arr=new int *[row];
for(int i=0;i<row;i++)
arr[i]= new int[col];//为每行分配空间(每行中有col个元素)
//输入二维数组的数
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
cin>>arr[i][j];
cout<<"*******************"<<endl;
//输出二维数组中的数
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
cout<<arr[i][j]<<" ";
cout<<endl;
}
//释放二维数组(反过来)
for(int i=0;i<row;i++)
delete[] arr[i];
delete[] arr;
return 0;
}
STL
map
//数据的插入
//示范1
map<int, string> mapStudent;
mapStudent.insert(pair<int, string>(1,“student_one”));/
//示范2
map<int, string> mapStudent;
mapStudent.insert(map<int, string>::value_type (1,“student_one”));
//示范3
map<int, string> mapStudent;
mapStudent[1] = “student_one”;
mapStudent[2] = “student_two”;
map<string, int> mapStudent;
string s;//插入就用m[s]=1或者m[s]++之类;
//数据查找
map<int, string>::iterator iter=mapStudent.find(1);
if(iter != mapStudent.end())
cout<<"Find, the value is "<<iter->second<<endl;
else cout<<"Do not Find"<<endl;
vector
next_permutation
//自动生成全排列
#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
int n;
while(scanf("%d",&n)&&n){
int a[1000];
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);//可以自行测试一下删除后的结果
do{
for(int i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}while(next_permutation(a,a+n));
}
return 0;
}
优先队列(priority_queue)
struct cmp{
bool operator()(string &x,string &y){
return x>y;//从小到大排序
}
};
priority_queue<string,vector<string>,cmp > q;
//这样的q是将存入的string从小到大
C++11
auto
自动类型推断【1】
for循环
【代码示例】
#include "stdafx.h"
#include<iostream>
#include<vector>
int main()
{
std::vector<int> arr;
arr.push_back(1);
arr.push_back(2);
for (auto n : arr)
{
std::cout << n << std::endl;
}
return 0;
}
断言(assert)
正常使用时assert(表达式);
提交OJ时对于那些不支持assert报RE的(比如说HDU)可以做如下处理
如果原先不是TLE那么头部加入
#define ASSERT(X) if(!(X)) while(true);
#define assert ASSERT
则如果为TLE则说明断言处有误(对于原本提交不是TLE的都有效)
如果原先不是MLE那么头部加入
#define ASSERT(X) if(!(X)){int sz=1;while(sz++){int *num=new int[sz];}}
#define assert ASSERT
如果变成MLE,则说明断言处有误(对于原本提交不是MLE的都有效)
【代码】
#define ASSERT(X) if(!(X)) while(true);
#define ASSERT(X) if(!(X)){int sz=1;while(sz++){int *num=new int[sz];}}
#define assert ASSERT
数据对拍(输入输出重定向-freopen)
【示例代码】
#include <stdio.h>
int main()
{
int a,b;
freopen("D:\\in.txt","r",stdin); //输入重定向,输入数据将从D盘根目录下的in.txt文件中读取
freopen("D:\\out.txt","w",stdout); //输出重定向,输出数据将保存在D盘根目录下的out.txt文件中
while(scanf("%d %d",&a,&b)!=EOF)
printf("%d\n",a+b);
fclose(stdin);//关闭重定向输入
fclose(stdout);//关闭重定向输出
return 0;
}
【数据对拍模板】
#include <bits/stdc++.h>
#define MAXT 1005
#define MAXN 110
#define debug false
const double pi=acos(-1);
const double eps=1e-8;
using namespace std;
struct inputnode{
int m;
double R;
double x[MAXN],y[MAXN],r[MAXN];
};
struct outputnode{
double myans,ans;
};
struct debugnode{
inputnode i;
outputnode o;
}DEBUG[MAXT];
void show_debugnode(debugnode x){
cout<<x.i.m<<" "<<x.i.R<<endl;
for(int i=0;i<x.i.m;i++){
cout<<x.i.x[i]<<" "<<x.i.y[i]<<" "<<x.i.r[i]<<endl;
}
cout<<"myans="<<x.o.myans<<endl;
cout<<"ans="<<x.o.ans<<endl;
return;
}
int fcmp(double x){
if(fabs(x)<eps) return 0;
return x<0?-1:1;
}
int main()
{
if(debug) freopen("D:\\ACM\\2018MultiTraining\\hdu-5\\data\\1005.in","r",stdin);
int t;
scanf("%d",&t);
for(int casenum=0;casenum<t;casenum++){
int m;
double R,ans=0;
cin>>m>>R;
if(debug) DEBUG[casenum].i.m=m,DEBUG[casenum].i.R=R;
ans=2*pi*R;
for(int debugm=0;debugm<m;debugm++){
double x,y,r;
cin>>x>>y>>r;
if(debug){
DEBUG[casenum].i.x[debugm]=x;
DEBUG[casenum].i.y[debugm]=y;
DEBUG[casenum].i.r[debugm]=r;
}
//程序执行内容
if(!debug) printf("%.8lf\n",ans);
if(debug) DEBUG[casenum].o.myans=ans;
}
if(debug) fclose(stdin);
if(debug){
freopen("D:\\ACM\\2018MultiTraining\\hdu-5\\data\\1005.out","r",stdin);
int t=0;
while(~scanf("%lf",&DEBUG[t].o.ans)){
if(fcmp(DEBUG[t].o.ans-DEBUG[t].o.myans)!=0){
show_debugnode(DEBUG[t]);
return 0;
}
t++;
}
cout<<"correct"<<endl;
}
if(debug) fclose(stdin);
return 0;
}
宏定义
带参宏定义【2】【3】
#ifdef #define #else #define #endif 可用于代码调试
#define DEBUG
#ifdef DEBUG
#endif
也可用于不同方案的比较
#define solution1
#define solution2
【代码示例】
//下述宏定义可以解决long long报warning问题
#ifdef unix
#define LLD "%lld"
#else
#define LLD "%I64d"
#endif
#define SCANFLL(x) scanf(LLD,&x)
#define PRINTLL(x) printf(LLD,x),printf("\n")
#include <bits/stdc++.h>
【代码示例】
//一个宏定义模板
#ifdef unix
#define LLD "%lld"
#else
#define LLD "%I64d"
#endif
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#define LL long long
#define maxn
#define INF 1 << 30
#define rep(i, j, k) for (int i = j; i <= k; i++)
#define For(i, j) for (int i = 1; i <= j; i++)
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
void file() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
大数模板(C/C++)
JAVA
BigDecimal
可持久化平衡树(C++ Pb_ds库 Rope)
参考文档【4】
声明
1)头文件
#include<ext/rope>
2)调用命名空间
using namespace __gnu_cxx;
底层原理
查了资料,大概可以称作可持久化平衡树,因为rope适用于大量、冗长的串操作,而不适合单个字符操作官方说明如下:
Though ropes can be treated as Containers of characters, and are almost Sequences, this is rarely the most efficient way to accomplish a task. Replacing an individual character in a rope is slow: each character replacement essentially consists of two substring operations followed by two concatenation operations. Ropes primarily target a more functional programming style.Inserting a character in the middle of a 10 megabyte rope should take on the order of 10s of microseconds, even if a copy of the original is kept, e.g. as part of an edit history.It is possible to view a function producing characters as a rope. Thus a piece of a rope may be a 100MByte file, which is read only when that section of the string is examined. Concatenating a string to the end of such a file does not involve reading the file. (Currently the implementation of this facility is incomplete.)
另,根据网上资料,rope本质是封装好的类似块状链表的东东,有人说是logn的,但也有说是n^0.5的。rope不支持一切数值操作,如第k大
小知识
先介绍几个可能使用到的函数
1)append()
string &append(const string &s,int pos,int n);//把字符串s中从pos开始的n个字符连接到当前字符串的结尾或a.append(b);
2)substr()
s.substr(0,5);//获得字符串s中从第零位开始长度为5的字符串(默认时长度为刚好开始位置到结尾)
定义/声明
rope str;
also
r=“abcdefg”
具体内容
总的来说,
1)运算符:rope支持operator += -= + - < ==
2)输入输出:可以用<<运算符由输入输出流读入或输出。
3)长度/大小:调用length(),size()都可以哦
4)插入/添加等:
push_back(x);//在末尾添加x
insert(pos,x);//在pos插入x,自然支持整个char数组的一次插入
erase(pos,x);//从pos开始删除x个
copy(pos,len,x);//从pos开始到pos+len为止用x代替
replace(pos,x);//从pos开始换成x
substr(pos,x);//提取pos开始x个
at(x)/[x];//访问第x个元素
访问
1)迭代器:不说,在竞赛是超时大忌
2)单点访问,直接用数组形式调用下标即可
应用
bzoj1269 文本编辑器
如果想看正常版本的看我的splay平衡树代码
实现操作:
1.(已知)move k:移动光标到目标,初始为0
2.(已知)prev:光标前移一个字符
3.(已知)next:光标后移一个字符
4.insert n s:在光标后插入长度为n的字符串s光标位置不变
5.delete n 删除光标后的n个字符,光标位置不变
6.rotate n 反转光标后的n个字符,光标位置不变
7.get 输出光标后一个字符,光标位置不变
solution
为实现反转操作且保证不超时,我们不调用rope自带的可怕函数,暴力构建两个rope,插入时一个正序插入一个倒序插入,区间即为子串赋值
基本操作
rope test;
test.push_back(x);//在末尾添加x
test.insert(pos,x);//在pos插入x
test.erase(pos,x);//从pos开始删除x个
test.copy(pos,len,x);//从pos开始到pos+len为止用x代替
test.replace(pos,x);//从pos开始换成x
test.substr(pos,x);//提取pos开始x个
test.at(x)/[x];//访问第x个元素
其算法复杂度n*(n^0.5),可以在很短的时间内实现快速的插入、删除和查找字符串,是一个很厉害的神器!
这里有英文版的详解【5】
【代码】bzoj/1269
牛客网2018暑期多校第3场-C(可持久化平衡树)
【题意】n个数(1-n),给m个操作,每次操作将当前的一段位置的数拿到最前面,要求输出进行完操作后依次位置的数
【题解】比赛的时候听说是splay树模板题,赛后又听说使用这个rope库(可持久化平衡树)就可以轻松AC
【代码】nowcoder/2018multi/3C
基础题
牛客网2018暑期多校第4场-F-Beautiful Garden-签到题
【题意】
【题解】
【代码】nowcoder/2018multi/4F
枚举
2018ICPC南京站网络预选赛- The writing on the wall
【Source】计蒜客
【TAG】铜牌题 枚举
【题解】这题看了网上题解才会做的【6】,但是实际上写完之后是O(nmm)的复杂度且WA了,对拍了AC程序后修正了BUG,然后就AC了…讲道理是应该TLE的,但是这题数据看来没有那么强。
【代码】jisuanke/2018ICPC/nanjing_pre/The writing on the wall
2018百度之星程序设计大赛资格赛1001-调查问卷
【TAG】状态压缩 bitset 枚举 签到题
【题解】问题数只有10个,直接暴力枚举(bitset状压)计算即可,其中我使用到了如下公式
∏ 1 ≤ i ≤ j ≤ n x i x j = 1 2 [ ( ∑ i = 1 n x i ) 2 − ∑ i = 1 n x i 2 ] ∏_{1≤i≤j≤n}x_i x_j=\frac 1 2 [(∑^n_{i=1}x_i )^2-∑_{i=1}^nx_i^2] 1≤i≤j≤n∏xixj=21[(i=1∑nxi)2−i=1∑nxi2]
来计算不同问卷对数的值,使用左边复杂度为O(n^2)使用右边复杂度为O(n)
【代码】baidustar\2018zigesai\1001
贪心
HDU-6385-rect
【Source】2018百度之星初赛第2场1006
【TAG】贪心
【难度】签到题
【代码】hdu/6385
模拟
2018ICPC南京站网络预选赛-GDY
【Source】计蒜客
【TAG】模拟 铜牌题
【题解】
直接模拟即可通过
【代码】jisuanke\2018ICPC\nanjing_pre\GDY
EOJ-3628- A Simple Convolution
【source】2018EOJ8月月赛A
【难度】签到题
【TAG】模拟
【代码】eoj/3628
牛客网2018暑期多校6A-Singing Contest
【TAG】模拟 签到题
【题解】贪心选择能击败对手的最小歌曲即可,我用了一个队列,每次2个队首的人出队比较,赢的人入队到队尾。
【代码】nowcoder\2018multi\6A
HDU-6330-Visual Cube-签到题
【题意】给定长宽高,输出立方体模拟图


【题解】2018杭电暑期多校L题签到题;直接找规律输出;每一行计算一下加在前面的点和加在后面的点数。
【代码】hdu/6330
HDU-6342- Expression in Memories-签到题
【题意】给定字符串包含0123456789±?要求把?替换为其他字符,使得其变为合法表达式(不能有前置0),如果无法做到输出IMPOSSIBLE
【TAG】模拟 签到题 SpecialJudge
【题解】
不合法情况:
(1)连续2个运算符
(2)前置0
(3)第1个位置和最后1个位置是运算符
问号处:
(1)有前置0的时候放运算符(不能在最后一个位置)
(2)无前置0的时候放‘1’
【代码】hdu/6342
搜索
深度优先搜索(DFS)
HDU-6341-Let Sudoku Rotate
【source】2018杭电暑期多校4J
【难度】比赛铜牌-命题人预估签到
【题意】给定一个从完好数独选定若干个格子进行逆时针旋转若干次后的数独(16*16),要求最小次数还原
【TAG】数独 DFS 最优化减枝 可行性减枝
【题解】
要还原就要把一些格子顺时针旋转,由题意一定有解
可以预处理的数据:每个格子最多顺时针0-3次
可行性减枝分析:对于某4行的4个格子,他们的行是否符合数独完全由这一行的4个格子决定,也就是说如果某一种操作使得某4行不符合数独,对其他行再进行操作也不会改变这4行的情况,列也是一样的,以此性质为基础进行可行性减枝。
DFS:依次搜索每一个格子的旋转次数
最优化减枝:当前操作数超过答案是停止搜索
可行性减枝:当前格子旋转这个次数后,使得某一行或某一列已经出现了冲突,那么停止搜索
【代码】hdu/6341
HDU-6351-Beautiful Now
【source】2018杭电暑期多校第5场1002-签到题
【题意】给定一个数字和交换次数,你可以交换数字的某2位,在交换过程中不能出现前导0的情况,问在给定交换次数内可以得到的最小值和最大值是多少
【TAG】搜索 贪心
【题解】
998244353 3
理论最小值 233445899
第1次交换 298944353
第2次交换 搜索1 238944953
第3次交换 搜索1 233944958
第2次交换 搜索2 238944359
第3次交换 搜索2 233944859
求出理论最大值和理论最小值,把当前数值比照理论值情况,从不符合的位置继续往下贪心的搜索。往下贪心只贪心之后数值最小的位置,搜索是要把这些位置都搜一遍(如果有多个位置的话),直接贪心和最后一个位置换是不对的
比如18900
如果贪心和最后一个换,是10908
对于只要求1次的时候是对的
但是如果要求2次的话,这样贪出来是
18900->10908->10098
而正确的搜索是
18900->10980->10089
【代码】hdu/6351
广度优先搜索(BFS)
二分
HDU-6383-p1m2
【Source】2018百度之星初赛第2场1004
【难度】签到题
【TAG】二分
【代码】hdu/6383
构造
ECNU ICPC/CCPC Trial Round #1-K-Kblack Playing Cards
【题意】给定n张纸牌,每个纸牌上的数字就是说它之后至少有这么多张牌说错了,要求给定一个这些牌的排列,使得恰好有K张牌说错
【题解】关键在于比如一个数字5,如果它在倒数5个位置或更靠后,那么它一定是错的。而一个小的数字如果在前面,则较有可能是对的。假设我们求出了一种排列的情况,满足里面恰好有K张牌是说错了,而其余牌都说对了,那么把已经说错的牌向后移不会改变它的布尔值,把已经说对了的牌向前移也不会改变它的布尔值,因此如果有解,那么一定存在这样的排列,前面都是对的,后面都是错的。并且,如果对的牌都比错的牌要小,且对的牌按照从大到小排序,错的牌按照从小到大排序,即【对大】->【对小】->【错小】->【错大】(对的都比错的小于等于),如果这样都无法满足题意的话,那么可以通过尝试交换任意2个数证明,交换后的结果只可能更远离结果。
【代码】eoj\ICPC CCPC Trial Round#1-K-Kblack Playing Cards
ECNU ICPC/CCPC Trial Round #1-I-Intersections
【题意】给出一个矩形所有中所有数字的相邻关系,要求还原出这个矩阵
【题解】根据每个数有多少数与之相邻(度),然后2就是顶角,3就在边上,4就在里面,依次填上就行了。
【代码】eoj\ICPC CCPC Trial Round#1-I-Intersections
EOJ-3630-Bad Queen
【Source】2018EOJ8月月赛B
【TAG】构造
【难度】签到题
【代码】eoj\3630
HDU-6300-Triangle Partion
【Source】2018杭电暑期多校1
【题意】
【TAG】签到题
【题解】按照x坐标排个序,按顺序输出即可
【代码】hdu\6300
曼哈顿距离最小生成树
参考【7】
输入输出外挂
题库
2018ICPC南京站网络预选赛-Lpl and Energy-saving Lamps
【Source】计蒜客
【TAG】铜牌题
【题解】
【代码】
铜牌题-前置:无
2018杭电暑期多校7-1011-Swordsman-HDU-6396
【TAG】
铜牌题-前置:无/LCT
2018杭电暑期多校7-1009-Tree-HDU-6394
【TAG】
铜牌题-前置:无
2018杭电暑期多校7-1005- GuGuFishtion-HDU-6390
【TAG】数论 欧拉函数
铜牌题-前置:无
2018杭电暑期多校3A-Ascending Rating-HDU6319-铜牌
【题意】
【TAG】单调队列 滑动窗口
【题解】
【代码】
铜牌题-前置:无
牛客网2018暑期多校7J-Sudoku Subrectangles
【TAG】
铜牌题-前置:无
牛客网2018暑期多校1D-Two Graphs
【TAG】图匹配 搜索
铜牌题-前置:无
牛客网2018暑期多校6I-Team Rocket
【TAG】树状数组 线段树 区间操作 在线处理
铜牌题-前置:无
2018杭电暑期多校第6场1002-bookshelf-HDU6363
(尝试1)铜牌题-前置:无
2018杭电暑期多校4E-HDU6336-Matrix From Arrays
【题意】
【TAG】
【题解】
【代码】
铜牌题-前置:01规划/分数规划
牛客网2018暑期多校5A-gpa
铜牌题-前置:无
牛客网2018暑期多校7C-Bit Compression
【TAG】卡常 搜索
(尝试1)铜牌题-前置:无
牛客网2018暑期多校2I-Car
(尝试*1)铜牌题-前置:无
2018杭电暑期多校1B-HDU6299-Balanced Sequence
【题意】
【TAG】
【题解】
【代码】
银牌题-前置:LCA
2018杭电暑期多校7-1008- Traffic Network in Numazu-HDU-6393
【TAG】
银牌题-前置:快速沃尔什变换(FWT)
牛客网2018暑期多校8H-Playing Games
【TAG】博弈论 尼姆博弈
(队友AC)铜牌题-前置:无
牛客网2018暑期多校8B-Filling Pools
【TAG】OEIS 找规律
(队友AC)签到题-前置:无
牛客网2018暑期多校8G-Counting regions
【TAG】OEIS 找规律
(队友AC)铜牌题-前置:无
2018杭电暑期多校7-1010-Sequence-HDU-6395
【TAG】矩阵快速幂 数论 递推
(队友AC)铜牌题-前置:无
牛客网2018暑期多校6C-Generation I
【TAG】排列组合 OEIS
【题解】队友在OEIS上发现了一个很强的规律,即得出的答案在除以m之后,首先n和m交换后的这个值是一样的,其次这个值在OEIS上直接有现成公式,所以就解决了。赛后发现其实是直接推公式也不是太难。
(队友AC)铜牌题-前置:无
2018杭电暑期多校第6场-1009-Werewolf-HDU6370
【TAG】推理 图论 环 基环树
(队友AC)签到题-前置:无
牛客网2018暑期多校7A-Minimum Cost Perfect Matching
【TAG】构造 异或
(队友AC)签到题-前置:无
2018杭电暑期多校1D-HDU6301-Distinct Values
【题意】
【TAG】
【题解】
【代码】
(队友AC)签到题-前置:无
牛客网2018暑期多校4D-Another Distinct Values
【题意】
【TAG】数学 构造
【题解】
【代码】
(队友AC)签到题-前置:无
牛客网2018暑期多校4G-Maximum Mode
【题意】
【TAG】
【题解】
【代码】
(队友AC)签到题-前置:无
牛客网2018暑期多校6D-Bulbasaur
【TAG】签到题
(队友AC)签到题-前置:无
牛客网2018暑期多校6J-Heritage of skywalkert
【TAG】随机 签到题
(队友AC)签到题-前置:无
2018杭电暑期多校1A-HDU6308-Time Zone
【题意】
【TAG】模拟
【题解】
【代码】
(队友AC)签到题-前置:无
2018杭电暑期多校第6场-1012-Pinball-HDU6373
【TAG】物理
银牌题-前置:无
牛客网2018暑期多校2G-transform
【题意】
【TAG】
【题解】
【代码】
二、综合题(现场题)
题库
(队友AC)签到题-前置:无
牛客网2018暑期多校5G-max
(队友AC)签到题-前置:无
牛客网2018暑期多校5J-plan
(队友AC)铜牌题-前置:无
2018杭电暑期多校2E-HDU6313-Hack it
【题意】
【TAG】构造 矩阵
【题解】
【代码】
(尝试*1)银牌题-前置:无
2018杭电暑期多校4G-HDU6338-Depth First Search
【题意】
【TAG】深度优先搜索 字典序
【题解】
【代码】
银牌题-前置:无
2018杭电暑期多校3M-HDU6331-Walking Plan
【题意】
【TAG】最短路 动态规划
【题解】
【代码】
银牌题-前置:无
牛客网2018暑期多校2J-farm
【题意】
【TAG】
【题解】
【代码】
金牌题-前置:无
牛客网2018暑期多校4I-Permutation
【题意】
【TAG】最短路 动态规划
【题解】
【代码】
三、动态规划
递推
HDU-2050-折线分割平面
【题意】求解n个折线能把平面分为几个区域
【题解】递推式 f ( n ) = f ( n − 1 ) + 4 ( n − 1 ) + 1 = f ( n − 1 ) + 4 n − 3 , f ( 1 ) = 2 f(n)=f(n-1)+4(n-1)+1=f(n-1)+4n-3,f(1)=2 f(n)=f(n−1)+4(n−1)+1=f(n−1)+4n−3,f(1)=2
具体的推导思路大概是考虑前面已经有 n − 1 n-1 n−1个折线了,然后现在又来一个折线,看成一个起点的2条射线,这样一交(尽可能往密集了交),按照新的射线大概可以分为3个区域,左射线左增加的区域数,右射线右增加的区域数,两射线之间增加的区域数,左边是 n − 1 n-1 n−1,右边是 n − 1 n-1 n−1,中间是 2 ( n − 1 ) 2(n-1) 2(n−1),再加1个自带的。反正是看着 n = 1 , n = 2 , n = 3 n=1,n=2,n=3 n=1,n=2,n=3的情况连蒙带猜的, n = 4 n=4 n=4再网上画也不好画了,这题也没法打表,还没有想到比较严谨的思路。
基础动态规划
最大连续子段和
HDU-1003
【题意】 n n n个数求最大连续子段和,同时输出子段的起始终止点(存在多个按照起始点顺序输出第1个,起始点相同的终止点尽可能小)
【题解】最大连续子段和模板题
【代码】hdu/1003
LIS(最长上升子序列)
单调栈优化
HDU-1087
【题意】n个正数,找到一个上升子序列,使得和最大,输出这个最大值,n规模1000
【题解】
d p [ i ] = m a x ( d p [ j ] ) + n u m [ i ] ( n u m [ j ] < n u m [ i ] & & j < i ) dp[i]=max(dp[j])+num[i](num[j]<num[i]\&\&j<i) dp[i]=max(dp[j])+num[i](num[j]<num[i]&&j<i),复杂度 O ( n 2 ) O(n^2) O(n2)
【代码】hdu/1087
LCIS(最长上升公共子序列)
HDU-1503-Advanced Fruits
【题意】给定2个字符串;要求1个最短的字符串,使得给定的2个字符串都是所求字符串的子序列。Special Judge。字符串长度范围1-100.
【题解】LCIS问题,对于非LCIS的部分,2个字符串的字母都要写。
d p [ i ] [ j ] dp[i][j] dp[i][j]表示第1个字符串考虑前i个字符,第2个字符串考虑前j个字符时的最大上升公共子序列长度
s [ i ] [ j ] s[i][j] s[i][j]表示考虑第1个字符串前i个字符和第2个字符串前j个字符时的题目所求字符串(也就是最大公共子串,还要加上非公共子串的部分)
当 a [ i ] = = b [ j ] a[i]==b[j] a[i]==b[j]时
d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + 1 , s [ i ] [ j ] = s [ i − 1 ] [ j − 1 ] + a [ i ] dp[i][j]=dp[i-1][j-1]+1,s[i][j]=s[i-1][j-1]+a[i] dp[i][j]=dp[i−1][j−1]+1,s[i][j]=s[i−1][j−1]+a[i]或 b [ j ] b[j] b[j]
当 a [ i ] ! = b [ j ] a[i]!=b[j] a[i]!=b[j]时
d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) dp[i][j]=max(dp[i-1][j],dp[i][j-1]) dp[i][j]=max(dp[i−1][j],dp[i][j−1])
若选取 d p [ i − 1 ] [ j ] dp[i-1][j] dp[i−1][j]则 s [ i ] [ j ] = s [ i − 1 ] [ j ] + a [ i ] s[i][j]=s[i-1][j]+a[i] s[i][j]=s[i−1][j]+a[i]
若选取 d p [ i ] [ j − 1 ] dp[i][j-1] dp[i][j−1]则 s [ i ] [ j ] = s [ i ] [ j − 1 ] + b [ j ] s[i][j]=s[i][j-1]+b[j] s[i][j]=s[i][j−1]+b[j]
初始时 d p [ 0 ] [ j ] dp[0][j] dp[0][j]和 d p [ i ] [ 0 ] dp[i][0] dp[i][0]均为0
s [ 0 ] [ 0 ] = " " , s [ 0 ] [ j ] s[0][0]="",s[0][j] s[0][0]="",s[0][j]为b串的前j个字符, a [ i ] [ 0 ] a[i][0] a[i][0]为 a a a串的前i个字符
【代码】hdu/1503
HDU-1159-LCIS模板题
【题意】求最长上升公共子序列
【题解】模板题
【代码】hdu/1159
背包问题
参考【11】
0-1背包
HDU-2602-Bone Collector
【题意】n个物品,告知n个物品价值、体积,给定背包容量,求解最大存放价值
【题解】0-1背包裸题,题目要求背包不必放满(初始化全0)
【代码】hdu/2602
完全背包
HDU-1114-Piggy Bank
【题意】给定背包容量,n个物品的体积和价值,要求背包刚好装满的最小价值
【题解】完全背包,修改状态转移方程为min,恰好装满,初始化除容量为0之外为非法
【代码】hdu\1114
多重背包
数位DP
HDU-2089-不要62
【题意】求 [ n , m ] [n,m] [n,m]区间中不含‘4’和‘62’的数字
【题解】数位DP经典入门题,dp[i][j]表示长度为i开头填j这个数字的方案数
d p [ i ] [ j ] = { 0 , j = 4 ∑ k = 0 , k ≠ 2 9 d p [ i − 1 ] [ k ] , j = 6 ∑ k = 0 9 d p [ i − 1 ] [ k ] , j ∉ { 4 , 6 } dp[i][j]=\left\{ \begin{aligned} 0 &,&j=4 \\ \sum_{k=0,k\neq2}^9 dp[i-1][k] &,&j=6 \\ \sum_{k=0}^9 dp[i-1][k]&,&j\notin\{4,6\} \end{aligned} \right. dp[i][j]=⎩⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎧
最低0.47元/天 解锁文章
5万+

被折叠的 条评论
为什么被折叠?



