五一 DAY 3
DAY 3 2019.4.30
动态规划DP
Dp是一个很抽象的东西
方法没有明显区别,很难总结套路
啥是DP?
DP等价于DAG!!!
(1)无后效性:DP的所有状态之间组成一个DAG
(2)最优子序列
(3)阶段性
(4)转移方程:如何计算状态
一般是顺序转移
有时候乱序,因为DP 是DAG,可以拓扑排序,然后从头for一遍
(5)状态:题目要算的东西
前置知识
简单的例子
斐波那契数列
0 1 1 2 3 5 8 13
F0=0 //边界条件
F1=1 //边界条件
Fn=Fn-1+Fn-2 // 转移方程
定义域,f0到正无穷
数列有一个边界条件,F0,F1
规定好的条件叫边界条件f0 , f1 , 不依赖于其他feibo数的值,直接求出值
f0,f1,.....fn 叫做状态,dp要求的未知东西,根据边界条件求出,依赖转移方程
对于DP,确定边界条件,转移方程,状态
F0,F1,.....Fn //状态
F0=0 //边界条件
F1=1 //边界条件
Fn=Fn-1+Fn-2 // 转移方程
(我们来看这个题)
以斐波那契数列为例,求斐波那契数列第n项
数组f[n] 表示 feibo第n 项
其他值加起来求 f[a] ,
用到再算,别人更新自己
#include<cstdio>
#include<iostream> using namespace std; int n,f[]; int main()
{
cin >> n;
f[]=;
f[]=; for (int a=;a<=n;a++)
{
f[a]=f[a-]+f[a-];
} cout << f[n] << endl; }
假设 f[a] 已经求出,考虑 f[a] 会影响到哪个值
自己更新别人
#include<cstdio>
#include<iostream> using namespace std; int n,f[]; int main()
{
cin >> n;
f[]=;
f[]=;
for (int a=;a<n;a++)
{
f[a+] += f[a];
f[a+] += f[a];
} cout << f[n] << endl;
}
Dfs搜索求出feibo
O(f[n]) 代码复杂度和feibo第n项大小一样
斐波那契数列通项公式
后项小于一
O与Feibo前项有关,指数级别复杂度,太慢
斐波那数列的第n项接近2^n
慢的原因:重复调用,每次产生一个新数都要多次计算已经算过的项
记忆化搜索:
记忆化可以解决的,递推或递归一定可以解决
记忆化搜索要多开一个数组,判断是否搜索过,空间多了一点
(矩阵加速实现logn)
保证每一项只被算一次, O(n)
#include<iostream> using namespace std; int f[n]; bool suan_le_mei[n]; //判断是否算过 int dfs(int n)
{
if (n==) return ;
if (n==) return ;
if (suan_le_mei[n]) return f[n]; //如果已经算过了,那就不算了,直接返回这个值 suan_le_mei[n] = true; //否则标记已算过
f[n] = dfs(n-) + dfs(n-); //计算 return f[n];
}// O(n) int main()
{
cin >> n;
cout << dfs(n) << endl; return ;
}
介绍4个有套路的
显然 Ans= r-l+1
考虑用数位DP
我们设 [ l , r ] 表示区间 l 到 r 中有多少个数字 (前缀和)
首先问题就有一步转化
[ l , r ] = [ 0 , r ] - [ 0 , l - 1 ]
那么问题的关键就在于求 [ 0 , x ]
十进制表示 x ,那么它的各位数字分别为
xn xn-1 xn-2 ..... x0
从最高位一位一位求[0,x] (区间有多少个数字)
等价于找到v,使得0≤v≤x
求v的个数
十进制表示 v ,那么它的各位数字分别为
vn Vn-1 Vn-2 ..... V0
V可能有前导0,但任然满足0≤v≤x
xn xn-1 xn-2 ..... x0
vn Vn-1 Vn-2 ..... V0
在第二行的每一位填上1-9的数,保证0≤v≤x
求v的方案数
填数:从高位开始,从n+1位置转移到n位
那么填Vn-3的时候, vn Vn-1 Vn-2 已经填
保证 vn Vn-1 Vn-2 <= xn xn-1 xn-2 (v前三位 ≤ x前三位)
希望填了Vn-3之后仍然满足0≤v≤x,前四位≤前四位
分类讨论:
(1) vn Vn-1 Vn-2 < xn xn-1 xn-2
此时 Vn-3 填 0--9 任意数
(2) vn Vn-1 Vn-2 = xn xn-1 xn-2
此时 Vn-3 填 0-- xn-3 任意数
f [ i ] [ j ] 由 f [ i - 1 ] [ j ’ ] 确定
先解释一下处理前导0
0 xn xn-1 xn-2 ..... x0
0 vn Vn-1 Vn-2 ..... V0
填完n+1位后,X,V,相等的方案数有1种,f[n+1][1] = 1;
#include<iostream> using namespace std; int l,r,z[]; //存储每一位 int f[][]; int solve(int x) //solve(i),表示0到i有多少个数
{
int n=;
while (x)
{
z[n] = x%;
x/=;
n++;
}
n--; memset(f,,sizeof(f)); //由于要两次DP,所以开始前清空数组 f[n+][] = ; //边界条件,处理前导零的状态 for (int a=n;a>=;a--) // 从头开始填
for (int b=;b<=;b++) //分类讨论
{
if (b==)
{
for (int c=;c<=;c++)
f[a][] += f[a+][b]; //保证始终v<x,方案数直接传递,
//c可以有很多选择,每次成立一次就加一遍上个状态
}
else
{
for (int c=;c<=z[a];c++)
{
if (c==z[a]) //填a位的时候方案就转移到了f[a][0]
//因为c可以填好几个数,每填一次就+=上一次的状态
f[a][] += f[a+][b]; else
f[a][] += f[a+][b];
}
}
} return f[][] + f[][]; // 各位填好后v<=x的方案总数
} int main()
{
cin >> l >> r; cout << solve(r) - solve(l-) << endl; return ;
}
G[ ][ ]表示数位之和
#include<iostream> using namespace std; int l,r,z[]; //存储每一位 int f[][];
int g[][]; int solve(int x) //solve(i),表示0到i有多少个数
{
int n=;
while (x)
{
z[n] = x%;
x/=;
n++;
}
n--; memset(f,,sizeof(f)); //由于要两次DP,所以开始前清空数组
memset(g,,sizeof(g)); f[n+][] = ; //边界条件,处理前导零的状态
g[n+][] = ; for (int a=n;a>=;a--) // 从头开始填
for (int b=;b<=;b++) //分类讨论
{
if (b==)
{
for (int c=;c<=;c++)
{
f[a][] += f[a+][b];
g[a][] += g[a+][b] + f[a+][b] * c; //拆分数字之和,a+1位和a位(每个方案数贡献一个)
}
}
else
{
for (int c=;c<=z[a];c++)
{
if (c==z[a])
{
f[a][] += f[a+][b];
g[a][] += g[a+][b] + f[a+][b] * c;
}
else
{
f[a][] += f[a+][b];
g[a][] += g[a+][b] + f[a+][b] * c;
}
}
}
} return g[][] + g[][]; //填完个位之后,统计所有 v <= x 的数位之和
} int main()
{
cin >> l >> r; cout << solve(r) - solve(l-) << endl; return ;
}
比如:135 合法 123非法
题目中有几个条件,就可以列一个多少维度的状态
这个题比之前多了一个条件,多一维状态
推荐题目:
纠正:
十年以前的省选题,到今天只是NOIP难度
上岁数的省选题不一定是省选难度
k可以填0---9
由于k!=11
所以可以质因数分解
k = 2a * 3b * 5c * 7d
so,可以把K拆成四个维度,降低复杂度
复杂度 a+b+c+d : log21018+ log31018+ log51018+ log101018
显然是n,
考虑DP
f[i]表示以i为根的子树中有多少个点
边界条件 f[leaf]=1
树形dp 由下至上一点点算上来
DFS 实现节点i子树有多少个点
对于每个点,枚举所有儿子,加起来子树之和,再加上自己的1个点
转移方程:
f[i]=f[son1]+f[son2]+.....f[sonn]+1
伪代码如下:
#include<iostream> using namespace std; int f[]; void read_tree() //存图 void dfs(int p) //DFS 实现节点i子树有多少个点
{
for (x is p's son)
{
dfs(x);
f[p] += f[x];
}
f[p] ++;
} int main()
{
cin >> n;
read_tree(); dfs();
cout << f[] << endl; return ;
}
直径:在树上找到两个点使得他们距离最远,这个距离就叫做直径
直径为三
提示:考虑一棵子树内部直径如何求
从一个点向下走两条路,合起来这两条路,就是一条路径
要找:
从一个点向下走最长的路径,和次长路径,合起来,对应这个拐点的最大路径
f[i][0] i向下最长路长度
f[i][1] i向下次长路长度
举例
最长路f[p][0]=max( f[p1][0] , f[p2][0] .... f[pn][0] )+1
次长路
f[p][1]=max( f[p1][0] , f[p2][1] .... f[pn][0] )+1
这样就错了,会出现
在找最长路的时候经过了p2,次长路的时候重复了p2,显然这是不可以的
所以直接删掉p2就完了
f[p][1]=max{ f[p1][0] , f[p3][0] .... f[pn][0] } +1
得到:
最长路 f[p][0]=max( f[p1][0] , f[p2][0] .... f[pn][0] )+1
次长路 f[p][1]=max{ f[p1][0] , f[p3][0] .... f[pn][0] } +1
最后枚举每一个点,每个点作为拐点,得到直径就是f[i][0]+f[i][1]
取出最大值
for( 1<= i <=n )
max{ f[i][0]+f[i][1] }
推荐题目:
P3304 [SDOI2013]直径
区间dp满足条件:
- 合并相邻的东西
- 把所有东西合并
F[l][r] 第 l 堆式子到第 r 堆式子合并为一堆的最小代价
边界条件: f[i][i]=0
最后一次合并,左右合并,两堆合成一堆
整个合并过程中没有改变石头顺序
所以两堆石头存在一个分界线,把它分成左右两堆
显然要找到一个分界点(断点)p,然后分开左右两边
f[l][p] f[p+1][r]
左右分开做,互不影响
所以枚举一下分界线(断点)p
最后结果就是:
f [ l ] [ r ] = min ( f [ l ] [ p] + f[ p + 1 ] [ r ] + sum [ l ] [ r ] )
f[l][p] 合并断点左边
f[p+1][r] 合并断点右边
sum[l][r] 合并这两堆(此处维护一个前缀和,更加方便)
[代码]:
由于求最小值,初始化最大 0x3f
最好不用0x7f,两个0x7f加起来就爆int
考虑如何循环
枚举左端点,右端点,断点
但这是错的
在求f[l][r]是没有计算f[l][r],但却需要他来更新
应该是小区间转移到大区间
枚举区间长度,按长度,从小到大
O(n3)
#include<iostream> using namespace std; const int INF=0x3f3f3f3f; int main()
{
cin >>n;
for (int a=;a<=n;a++)
cin >> z[a];
memset(f,0x3f,sizeof(f)); //由于求最小值,初始化最大 0x3f for (int a=;a<=n;a++)
f[a][a] = ; //边界条件 for (int len=;len<=n;len++)
for (int l=,r=len; r<=n; l++,r++)
for (int p=l;p<r;p++)
f[l][r] = min(f[l][r],f[l][p]+f[p+][r]+sum[l][r]); // cout << f[][n] << endl; return ;
}
P1880 [NOI1995]石子合并
上一题a1 an 不相邻,本题a1 an相邻,
所以要补区间,扩成两倍,但还是只做了一遍DP
f[1][n]是考虑a1 an 不相邻
f[2][n+1]是考虑a1 an相邻,但是a2 a1 不相邻
所以考虑一遍各种情况,每次都会有一个断开的位置,找出断开哪个位置使得结果最小
推荐题目:
P1063 能量项链
给出点的坐标
(x1,y1)(x2,y2)(x3,y3)……(xn,yn)
有一个人一开始在一号点
出发,把其余的点都走至少一遍,使得路径最短
这样也是可以的
这叫TSP问题
(旅行商问题)
经典的NP-hard问题 最快也至少是O(2n),n在指数上
(continue)
结论:
最优情况下,每个点只去一次
DP每一步枚举所有可能的情况
目前停留在5,它可以有三种情况的转移,因为还有三个点没走
DP转移:
希望把集合变成下标
目前保持的状态是集合,要求压成数
构造一个n位二进制数
每个元素只有可能在或者不在集合里
在 1
不在 0
所以说这个二进制数与集合{1,4,5}等价
S,已经走过的点的集合
F[ s ][ i ]从起点出发,走过集合s里的点,停留在i,所走过的最小距离
初始化f[1][1]=0
转移:考虑怎么走
转移
枚举j点,如果没走过它,我们把他加进去s试试
相应的最短距离要更新
转移方程
把s的第j位从0变成1
如果从i走到j比从起点到j近
#include<cstdio>
#include<iostream> using namespace std; const int maxn=; int n; double f[<<maxn][maxn]; //F[2^n][n]这么大就好 double dis(int i,int j)
{
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
} int main()
{
cin >> n;
for (int a=;a<n;a++) //a下标 0-n-1
cin >> x[a] >> y[a]; for (int a=;a<(<<n);a++) //手动初始化数组
for (int b=;b<n;b++)
f[a][b] = 1e+; //要求最小值,手动无穷大 f[][] = ; //初始化边界 for (int s=;s<(<<n);s++) //枚举S
for (int i=;i<n;i++) //枚举最后停留在那个点,停在i点
if ( ((s>>i) & ) == ) // 看S二进制第i位是0还是1, 保证i在集合 s里
for (int j=;j<n;j++) // 枚举没走过的点 (j位一定为0)
if ( ((s>>j) & ) == ) //s>>j,那么i位就到了第0位
f[s|(<<j)][j] = min(f[s|(<<j)][j] , f[s][i] + dis(i,j));//转移方程 double ans = 1e+;
for (int a=;a<n;a++) //不可能停在起点0号,所以从1枚举
ans = min (ans , f[(<<n)-][a]); //2的N次方减一就是N个位都是1 ,也就是都走过了一遍点 cout << ans <<endl; }
它的时间复杂度是O(n^2 * s^n)
空间复杂度O(2^n * n)
(一秒钟的运算量在3*10^8~10^9之间)
差不多n<=20
补充一些复杂度有关的知识
n<=12(O(n!)的复杂度,直接暴搜)
n<=22 或20(状压O(n^2 * s^n))
n<=32 (直接放弃)
n<=50 (直接放弃)
n<=100 (O(n^3))
n<=1000 (O(n^2))
n<=10^5 (数据结构 O(nlogn))
n<=10^6 (线性算法 O(n))
n>10^6(O(1))
2019.7.17又讲一遍
- 平面上N个点,第i个点坐标(xi,yi),从1号点出发,在平面上任意走,求走遍所有点再回来的最短路径
使得距离最短,一个点没必要走两次,每次从没走过的点选一个出来
f[s][i] i 在i点,s走过了哪些点
状态压缩:把一个数组压缩成一个数
自己更新别人
所以我们要找没走过的点,枚举j,看看s的第j位二进制位是不是0
最后答案看看停在那个点,最后还要回来
#include<iostream> using namespace std; double f[][];
double x[],y[]; int main()
{
cin >> n;
for (int a=;a<n;a++)
cin >> x[a] >> y[a];
f=∞
f[][]=;
for (int s=;s<(<<n);s++)
for (int i=;i<n;i++)
if (f[s][i] < ∞)
{
for (int j=;j<n;j++)
if ( ((s>>j) & ) == )
{
int news = s | (<<j); //加上这个数字
f[news][j] = min(f[news][j],f[s][i] + dis(i,j));
}
}
for (int i=;i<n;i++)
ans=min(ans, f[(<<n)-][i] + dis(i,)); return ;
}
O(2^n * n^2)
N<=22或者N<=20
一定是先枚举s,然后s从小到大,因为走过的点是越来越多的
推荐题目:
P1171 售货员的难题
题目每多一个条件就多一个维度(至少保留暴力分。。)
Fij 从起点走到 i,j 的方案数
每个坐标都可以向右或下走,除了边界,每个点由左边的点或上边的点转移过来
边界只能由一个方向转移过来
边界条件:f1j=fi1=1
转移方程:fij=fi-1,j+fi,j-1
其实也就是这样
Cn-1n+m-2
希望走过的路径最大
变化量:走的过程中,位置变化
f[i][j] 走到(i,j)时走过路径的最大值
可以从左上角或者正上方转移过来
转移方程:f[ i ][ j ] = max( f[ i-1 ][ j ] , f[ i-1 ][ j-1 ] ) + a[ i ][ j ]
Joyoi
数字三角形2
PS: 实在不行加一维
f[i][j] 走到(i,j) %100 后的最大值
错误
前面的最优不一定保证后面最优
比如你现在在98 99中选择,99一定最优,但是下一步再选,就会降为hin小的数
维度不够加一维
所以考虑加一维度
bool f[i][j][k]表示走到[i][j]时的路径和%100=k是否可行
#include<iostream> using namespace std; bool f[233][233][233]; //bool数组 int main()
{
cin >> n;
for (int i=1;i<=n;i++)
for (int j=1;j<=i;j++)
cin >> a[i][j]; f[1][1][a[1][1] % 100] = true; //初始化
for (int i=1;i<n;i++)
for (int j=1;j<=i;j++)
for (int k=0;k<100;k++)
if (f[i][j][k]) //判断之前是否可达,否则走就没必要
{
f[i+1][j][(k+a[i+1][j])%100]=true;
f[i+1][j+1][(k+a[i+1][j+1])%100]=true;
} for (int j=1;j<=n;j++) //最后枚举在哪一列
for (int k=0;k<100;k++)
if (f[n][j][k]) ans=max(ans,k);
cout << ans << endl; return 0;
}
(和导弹拦截有异曲同工之妙)
数据加强到n<=105
用数据结构 线段树 加速
系统的学习详见背包九讲
好趴下面放3个背包问题:
01背包
例题:采药
N个物品,M个体积
物品i,体积vi,价值wi
头疼:设计状态
放物品,考虑有什么未知量???
第一维:放了多少物品,[i]放好了i个物品
第二维:体积 [j] 已经放进去的物品,体积是多少
F[i][j] 放进i个物品,体积为j的最大价值
放进物品的编号<=i ,每个物品可以放或者不放,j已经放进去i个物品的体积之和
如何转移???
每次都考虑好了前i种物品,那么就考虑第i+1放或者不放
如果不放第i +1个物品,体积不变,价值不变
放了后体积会+vi,价值+wi
f[ i ][ j ] = max( f[ i-1 ][ j ] , f[ i-1 ][ j-v[i] ] + wi )
外层for循环维度
状态转移
J要判断啊,不可以超过背包容积
最后答案不一定是f[n][m],因为不一定体积越大价值越大,但是答案一定是考虑了所有n个物品,所以for一遍体积,ans取max
for (int i=1;i<=n;i++)
for (int j=0;j<=m;j++)
{
f[i][j] = f[i-1][j];
if (j >= v[i]) f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);
} int ans=0;
for (int a=0;a<=m;a++)
ans = max(ans,f[n][a]);
cout << ans << endl;
无限背包问题
从别人转移到自己
放0个:f[i-1][j]
放1个:f[i-1][j-vi]
放2个:f[i-1][j-2*vi]
放k个:f[i-1][j-k*vi]
可以枚举第i个物品到底放了几个
for (int i=1;i<=n;i++)
for (int j=0;j<=m;j++)
for (int k=0;k*v[i]<=j;k++)
f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
要判断k*v[i]<=j,保证体积不会爆炸
But 3层循环 O(n^3),慢了hin多
如何优化???
其实不需要降维,只需要把01背包改一下
f[ i ][ j ] = max( f[ i ][ j ] , f[ i ][ j-v[i] ] + w[ i ] )
之前是由i-1这种i的上一层状态转移过来的
此时就可以同一行的转移,横向转移,转移多少次就相当于一种物品放了多少个
复杂度 : O(nm)
for (int i=1;i<=n;i++)
for (int j=0;j<=m;j++)
{
f[i][j] = f[i-1][j];
if (j >= v[i]) f[i][j] = max(f[i][j],f[i][j-v[i]]+w[i]);
}
int ans=0;
for (int a=0;a<=m;a++)
ans = max(ans,f[n][a]);
cout << ans << endl;
有限背包问题
直接k枚举多少次 O(n^3)
考虑优化???
比如现在一个物品能放13次
造体积为vi,价值为wi,只能用1次的物品
造体积为2vi,价值为2wi,只能用1次的物品
造体积为4vi,价值为4wi,只能用1次的物品
造体积为6vi,价值为6wi,只能用1次的物品
变成捆绑包的组合
01背包问题
O(n^2 * k)
如何处理捆绑包大小???
相当于二进制拆分
(1)如果一个数字可以被2^k这样111111分解,那么很显然捆绑包组合起来可以实现所有值
(2)那如果不能111111这样分解,最后一定会剩下一个数字,把这个数字打包成一个捆绑包,也就是你算的时候,先算上这个数字,然后后面就变成一个可以被1111拆分的,就又回到上面情况
拆出来捆绑包个数k≈logn
所以复杂度就是O( nm logn )
只需要读入处理一下
#include<iostream> using namespace std; int n,m,w[233],v[233];
int f[233][233]; int main()
{
cin >> n >> m;
int cnt = 0;
for (int a=1;a<=n;a++)
{
int v_,w_,z;
cin >> v_>> w_ >> z; int x = 1;
while (x <= z)
{
cnt ++;
v[cnt] = v_*x;
w[cnt] = w_*x;
z-=x;
x*=2;
}
if (z>0) //Z最后有剩余,新建一个捆绑包
{
cnt ++;
v[cnt] = v_*z;
w[cnt] = w_*z;
}
}
n=cnt;
for (int i=1;i<=n;i++)
for (int j=0;j<=m;j++)
{
f[i][j] = f[i-1][j];
if (j >= v[i]) f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);
}
int ans=0;
for (int a=0;a<=m;a++)
ans = max(ans,f[n][a]);
cout << ans << endl;
return 0;
}
最后是一个无处安放的DP
P4408 [NOI2003]逃学的小孩
以及网址
五一 DAY 3的更多相关文章
- 带你找到五一最省的旅游路线【dijkstra算法推导详解】
前言 五一快到了,小张准备去旅游了! 查了查到各地的机票 因为今年被扣工资扣得很惨,小张手头不是很宽裕,必须精打细算.他想弄清去各个城市的最低开销. [嗯,不用考虑回来的开销.小张准备找警察叔叔说自己 ...
- 五一出门必备的手机APP神器 让你瞬间大开眼界
如今我们手机上有各种各样的软件,但是比较实用的又有哪些呢?所以每次大家都会花上很久的时间去查找满意的软件吧!今天就给大家送上一波福利,因为五一小长假就要到来了,说不定大家会使用到呢! 轻颜相机 轻颜相 ...
- 五一,期待一场这样的旅行,提前预祝Csdner五一快乐
五一,期待一场这样的旅行,提前预祝Csdner五一快乐 五一,你是否期待一次这样的旅行: 住在一间安静优美的小屋,在鸟鸣中起床,推窗有花香铺面而来.早餐过后,在阳光温暖的抚摸里,骑车踏青或光脚奔跑. ...
- GDOI2017 五一游玩记
GDOI2017 到辣! 在五一比赛,成功躲了两天文化课. Day 0 早上睡到挺晚,想着同学在上课,我在睡觉,暗爽... 动车上,拿起电脑就是颓废,打模板!(然而真相是打了两个模板就开始颓了) 一天 ...
- 五一巨献,问答有礼,105QB送给IT互联网界的劳动人民
活动主题:五一巨献,问答有礼,105QB送给IT互联网界的劳动人民活动时间:4月30日晚上10点~5月2日晚上10点活动期数:第1期,20150401 奖品:105QB获奖人数:20人1~5:每人10 ...
- Python 爬取 13 个旅游城市,告诉你五一大家最爱去哪玩?
五一假期已经结束,小伙伴是不是都还没有玩过瘾?但是没办法,还有很多bug等着我们去写,同样还有需要money需要我们去赚.为了生活总的拼搏. 今年五一放了四天假,很多人不再只是选择周边游,因为时间充裕 ...
- 五一DAY1数论学习笔记
by ruanxingzhi 整除性 如果a能把b除尽,也就是没有余数,则我们称a整除b,亦称b被a整除.(不是除以,是整除!!) 记作:\(a|b\) |这个竖杠就是整除符号 整除的性质 自反性 对 ...
- 五一 DAY 5
五一 DAY 5 V 点 1----n E 边 /* Given a graph with N nodes and M unidirectional edges. Each edge e_i ...
- 五一 DAY 4
DAY 4 2019.5.1 PART 1 进制转化 10 = 23+21= 1010(2) = 32+30= 101(3) 进制转化常见问题: 1.十进制数 x ----&g ...
- 五一 DAY 7
五一 DAY 7 P1514 引水入城 P1311 选择客栈 题解: P1315 观光公交 题解: 设 wait i 为最晚到达的旅客 arrive i 为到达i 的时刻 arrive i =max ...
随机推荐
- dedecms 调用全部导航+二级导航
{dede:channelartlist row=5 typeid='top'} <li><a class="hide" href="{dede:fie ...
- C++ Concurrency In Action 一些重点
全部来自于gitbook C++并发编程(中文版) 需要对一个还未销毁的std::thread对象使用join()或detach().如果想要分离一个线程,可以在线程启动后,直接使用detach() ...
- django用户投票系统详解
投票系统之详解 1.创建项目(mysite)与应用(polls) django-admin.py startproject mysite python manage.py startapp polls ...
- linux chattr:配置文件隐藏属性;lsattr:显示文件属性
1 chattr [+-=][ASadistu] 文件或目录名称 选项与参数: + :在原有参数设定基础上,追加参数.- :在原有参数设定基础上,移除参数.= :更新为指定参数设定.A:文件或目 ...
- Reflector破译
一:安装: 这个在包里,自己安装 二:注册 1. 断网2. 运行.NET Reflector,点击Help -> Activate 3. 运行注册机,复制注册机生成的序列号,粘贴到.NET Re ...
- IList,List<T>转换为DataTable 常用收藏
List<info> infos = Dal.GetInfos(); DataTable dt = new DataTable(); dt.Columns.Add("cName& ...
- 【2019.3.20】NOI模拟赛
题目 这里必须标记一下那个傻逼问题,再不解决我人就没了! 先放一个 $T3$ $20$ 分暴力 #include<bits/stdc++.h> #define rep(i,x,y) for ...
- Java Arrays.asList注意事项
https://blog.csdn.net/kusedexingfu/article/details/77824189
- 数组与pandas模块
'''数组与pandas模块''' # numpy模块:用来做数据分析,对numpy数组(既有行又有列)--矩阵进行科学运算 # tensorflow/pytorch(数学专业/物理专业/计科专业硕士 ...
- buuctf@easyre