AlvinZH掉坑系列讲解(背包DP大作战H~M)
本文由AlvinZH所写,欢迎学习引用,如有错误或更优化方法,欢迎讨论,联系方式QQ:1329284394。
前言
动态规划(Dynamic Programming),是一个神奇的东西。DP只能意会,不可言传。大家在做DP题的时候一定要理清思路,一般是先不管空间,毕竟以空间换时间,大多数题都是先卡时间再卡空间的。
DP具备的两个要素:最优子结构和子问题重叠,见《算法导论》225页。简单来讲就是问题是一个由多决策产生最优值的最优化问题。
- 最优化原理:其子问题的最优会导致全局最优,具有最优子结构的性质。这是运用DP的"前提",是否符合最优化原理是一个问题的本质特征。如果不满足最优化原理,那最开始所做的决策都是徒劳的。
- 无后效性:当前状态如果确定,以后过程的演变将不再受当前状态以前的各状态和以前的决策影响。这是运用DP的"条件",DP按次序去求每阶段的解,如果一个问题有后效性,那么这样的次序便是不合理的。一个问题的某个DP决策方法可能具有后效性,通过重新划分阶段,重新选定状态,或者增加状态变量的个数等手段,是可以把问题转化为满足无后效性的。所以决策的"顺序"也是问题的关键。
接下来通过几道经典的题目,简单练习一下DP,比赛题目连接:BUAAOJ-DP大作战 H~M题。
899 AlvinZH掉坑里了(H)
思路
简单DP。简单判断符合运用DP要求,求得到达某个点的最大金币数,至多只要比较两点(左点&上点)的最大金币数,即满足最优子结构。
\(dp[i][j]\) :表示走到点(i,j)时取得的最大金币数。
状态转移方程: \(dp[i][j] = max(dp[i - 1][j],dp[i][j - 1]) + M[i][j]\) 。
小技巧:①初始化为-INF;②真实数据存于[1n][1m]中,边缘统一。
参考代码
//
// Created by AlvinZH on 2017/10/17.
// Copyright (c) AlvinZH. All rights reserved.
//
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
int M[505][505];//矩阵数据
int dp[505][505];//到达点(i,j)时最大金币个数
inline int MAX(int i, int j) {
if(dp[i - 1][j] > dp[i][j - 1]) return dp[i - 1][j];
else return dp[i][j - 1];
}
int main()
{
int n, m;
while(~scanf("%d %d", &n, &m))
{
memset(dp, -INF, sizeof(dp));
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
scanf("%d", &M[i][j]);
dp[1][1] = M[1][1];
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
if(dp[i][j] < 0) dp[i][j] = MAX(i, j) + M[i][j];
printf("%d\n", dp[n][m]);
}
}
/*
* 简单DP
* dp[i][j]表示走到点(i,j)时取得的最大金币数。
* 状态转移方程:dp[i][j] = max(dp[i - 1][j],dp[i][j - 1]) + M[i][j]。
*/
900 AlvinZH又掉坑里了(I)
思路
难题。
错误思路:贪心。运用上一题的写法,先走一次,路径置零,再来一次,两次最大值相加。你会发现你样例都过不了(要是放个恰好满足的样例不知道要WA多少次)。仔细一想,两次最优加起来还会是最优吗?真不一定,看这题就知道了。
既然不能分两次处理,那就同步处理吧。如何同步呢?多路DP,即想象两个人同时从左上走到右下,保证在同一点只取一次,求两人最大金币数和。用四维数组dp[205][205][205][205]?看着就挺吓人的,不过简单易懂,状态转移方程也可以很快得出:dp[i][j][x][y]=max{dp[i-1][j][x-1][y],dp[i-1][j][x][y-1],dp[i][j-1][x-1][y],dp[i][j-1][x][y-1]},代表两人到达(i,j)和(x,y)时的最大金币数。虽然明知会MLE,这一步的思考是有必要的,因为这是优化的基础。
发现惊喜:上述状态转移方程四个决策中有 \(i+j=x+y\) ,故可以轻易的把四维降成三维。这里有两种方法优化:
- 第一种方法稍微作优化,需要dp[405][205][205]。其中dp[step][x][y]:表示第step步时(两人一起走),第一个人在第x行,第二个人在第y行的最大收益,答案为dp[m + n][n][n]。两人坐标为(x,step-x)、(y,step-y),两个人在同一行时,一定在同一列,需要注意走到同一点时的处理方法。状态转移如下,四种决策(下下,下右,右下,右右)去最优,具体见参考代码一。
//下下,下右,右下,右右四者取最大值
dp[i][j][k] = MAX(dp[i-1][j-1][k-1], dp[i-1][j][k-1], dp[i-1][j-1][k], dp[i-1][j][k]);
if (j == k)//走到同一行,必定在同一列,所以确定到达A[j][i - j]同一点
dp[i][j][k] += M[j][i-j];
else//走到不同行,所以确定到达A[j][i-j]、A[k][i-k]两点。
dp[i][j][k] += (M[j][i-j] + M[k][i-k]);
- 第二种方法优化更佳,也易懂,需要dp[205][205][205]。其中dp[i][j][k]表示第一个人走到(i,j),第二个人走到横坐标为k,由于两人一起走,可以算出第二人坐标为(k,i+j-k)。这里可以直接避免走到同一点,k!=i即可。状态转移方程如下,同样是取四种决策最优,具体见参考代码二。
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
for(int k = 1; k <= n && k <= (i+j); ++k)
{
int t = (i+j)-k;
if ( k != i )//保证不重复
dp[i][j][k] = M[i][j]+M[k][t]+MAX(dp[i-1][j][k],dp[i][j-1][k],dp[i-1][j][k-1],dp[i][j-1][k-1]);
}
这两种优化很相似,而第二种比第一种空间整整小了一倍,有人问为什么还要放在这里讨论,因为,第一种方法还可以继续优化,我们发现,在状态转移方程中,dp[i][][]只与dp[i-1][][]有关,这意味着什么?这意味着可以把第一维继续优化,即数组变为dp[2][205][205],采用滚动数组,把第一维循环利用。状态转移方程如下,具体可见参考代码三。
int cur = 0;
for (int i = 2; i <= n + m; i++) {
cur ^= 1;
for (int j = 1; j <= n&&i - j >= 0; j++) {
for (int k = 1; k <= n&&i - k >= 0; k++) {
//下下,下右,右下,右右四者取最大值
dp[cur][j][k] = MAX(dp[cur^1][j-1][k-1], dp[cur^1][j][k-1], dp[cur^1][j-1][k], dp[cur^1][j][k]);
if (j == k)//走到同一行,必定在同一列,所以确定到A[j][i - j]一点
dp[cur][j][k] += M[j][i-j];
else//走到不同行,所以确定到A[j][i-j]、A[k][i-k]两点。
dp[cur][j][k] += (M[j][i-j] + M[k][i-k]);//右右
}
}
}
三种方法评测记录对比如下:
参考代码一
//
// Created by AlvinZH on 2017/10/17.
// Copyright (c) AlvinZH. All rights reserved.
//
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
int m, n;
int M[201][201];
int dp[402][201][201];
inline int MAX(int a, int b, int c, int d) {
int minAns = a;
if(minAns < b) minAns = b;
if(minAns < c) minAns = c;
if(minAns < d) minAns = d;
return minAns;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &M[i][j]);
for (int i = 2; i <= n + m; i++) {
for (int j = 1; j <= n && i - j >= 0; j++) {
for (int k = 1; k <= n && i - k >= 0; k++) {
//下下,下右,右下,右右四者取最大值
dp[i][j][k] = MAX(dp[i-1][j-1][k-1], dp[i-1][j][k-1], dp[i-1][j-1][k], dp[i-1][j][k]);
if (j == k)//走到同一行,必定在同一列,所以确定到达A[j][i - j]同一点
dp[i][j][k] += M[j][i-j];
else//走到不同行,所以确定到达A[j][i-j]、A[k][i-k]两点。
dp[i][j][k] += (M[j][i-j] + M[k][i-k]);
}
}
}
printf("%d\n",dp[n + m][n][n]);
}
return 0;
}
参考代码二
//
// Created by AlvinZH on 2017/10/17.
// Copyright (c) AlvinZH. All rights reserved.
//
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int m, n;
int M[201][201];
int dp[201][201][201];
inline int MAX(int a, int b, int c, int d) {
int minAns = a;
if(minAns < b) minAns = b;
if(minAns < c) minAns = c;
if(minAns < d) minAns = d;
return minAns;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
scanf("%d", &M[i][j]);
dp[1][1][1] = M[1][1];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
for(int k = 1; k <= n && k <= (i+j); ++k)
{
int t = (i+j)-k;
if ( k != i )//保证不重复
dp[i][j][k] = M[i][j]+M[k][t]+MAX(dp[i-1][j][k],dp[i][j-1][k],dp[i-1][j][k-1],dp[i][j-1][k-1]);
}
printf("%d\n", dp[n][m-1][n-1] + M[n][m]);
}
}
参考代码三(最优)
//
// Created by AlvinZH on 2017/10/17.
// Copyright (c) AlvinZH. All rights reserved.
//
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int m, n;
int M[201][201];
int dp[2][201][201];
inline int MAX(int a, int b, int c, int d) {
int minAns = a;
if(minAns < b) minAns = b;
if(minAns < c) minAns = c;
if(minAns < d) minAns = d;
return minAns;
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &M[i][j]);
//发现每一步只与前一步有关,可以滚动数组,把一维滚动掉。
int cur = 0;
for (int i = 2; i <= n + m; i++) {
cur ^= 1;
for (int j = 1; j <= n&&i - j >= 0; j++) {
for (int k = 1; k <= n&&i - k >= 0; k++) {
//下下,下右,右下,右右四者取最大值
dp[cur][j][k] = MAX(dp[cur^1][j - 1][k - 1], dp[cur^1][j][k - 1], dp[cur^1][j - 1][k], dp[cur^1][j][k]);
if (j == k)//走到同一行,必定在同一列,所以确定到A[j][i - j]一点
dp[cur][j][k] += M[j][i - j];
else//走到不同行,所以确定到A[j][i - j]、A[k][i - k]两点。
dp[cur][j][k] += (M[j][i - j] + M[k][i - k]);//右右
}
}
}
printf("%d\n",dp[cur][n][n]);
}
return 0;
}
901 AlvinZH双掉坑里了(J)
思路
简单DP。简化问题:将n个金币放入m个盒子,无空盒。
直接上dp吧,dp[i][j]:将i个金币放入j个盒子的方法数。此题的关键在于如何找到状态转移方程,很有可能会计算重复的方法。我们把答案分成两部分:
①放完之后所有盒子金币数量大于1;
②放完之后至少有一个盒子金币数量为1。
这样分可以保证不会有重复计算。状态转移方程: \(dp[i][j] = dp[i-j][j] + dp[i-1][j-1]\) 。
① \(dp[i-j][j]\) :将(i-j)个金币放到j个盒子,然后这j个盒子每个再放1个金币。表示的是将i个金币分成所有盒子金币数量大于1的方案总数。例如,求9分解成3份,6(9-3)分成3份可以分为{1,1,4}{1,2,3}{2,2,2},则9可以分为{2,2,5}{2,3,4}{3,3,3},共3种。
② \(dp[i-1][j-1]\) :将(i-1)个金币放到(j-1)个盒子,再来一个盒子放1个。表示的是将i个金币分成至少有一个盒子金币数量为1的方案总数。例如,求9分解成3份,8(9-1)分成2份可以分为{1,7}{2,6}{3,5}{4,4},则9可以分为{1,1,7}{1,2,6}{1,3,5}{1,4,4},共4种。
难点在于如何避免重复,这里处理得十分巧妙,请细细体会。
参考代码
//
// Created by AlvinZH on 2017/10/23.
// Copyright (c) AlvinZH. All rights reserved.
//
#include <cstdio>
#include <cstring>
#define MOD 1000007
int n, m;
int dp[10005][1005];
int main()
{
while(~scanf("%d %d", &n, &m))
{
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if(i - j >= 0)
dp[i][j] = (dp[i-j][j] + dp[i-1][j-1]) % MOD;
}
}
printf("%d\n", dp[n][m]);
}
}
902 AlvinZH叒掉坑里了(K)
思路
简单DP。与上一题十分相似,问题简化为:将n个金币放入至多m个盒子,不存在相等数量金币的盒子。
dp[i][j]:将i个金币放入j个盒子的方法数。本题同样可以沿用上一题思想,把答案分成两部分。但是有一个问题是不能有相同数量金币的盒子,如果像上一题一样处理,我们会出现多个1的情况,需要避免这些情况。
①放完之后所有盒子金币数量大于1;
②放完之后只有一个盒子金币数量为1。
这样分可以保证不会有重复计算,而且不会有相同。状态转移方程: \(dp[i][j] = dp[i-j][j] + dp[i-j][j-1]\) 。
① \(dp[i-j][j]\) :将(i-j)个金币放到j个盒子,然后这j个盒子每个再放1个金币。表示的是将i个金币分成所有盒子金币数量大于1的方案总数。
② \(dp[i-j][j-1]\) :将(i-j)个金币放到(j-1)个盒子,然后这(j-1)个盒子每个再放1个金币,最后再来一个盒子放1个金币。表示的是将i个金币分成至少有一个盒子金币数量为1的方案总数。
对比上一题,状态转移方程仅仅差了一个字符
难点在于如何避免重复以及相同数目,这里处理得十分巧妙,请细细体会。
优化问题
本题需要注意内存限制,dp[50005][50005]是会MLE的。由于本题要求分成不同的数目,1+2+3+...+m=n,可以得到 \(m<sqrt(2_n)\) ,于是dp数组变成dp[50005][350]。时间复杂度为 \(O(n_sqrt(2n))\) 。具体见参考代码一。
与第二题相似,我们发现,dp[i][j]只与dp[][j]和dp[][j-1]有关,那么这里可以对空间再次优化,dp数组变为dp[50005][2],具体操作见参考代码二。真tm神奇啊~
参考代码一
//
// Created by AlvinZH on 2017/10/23.
// Copyright (c) AlvinZH. All rights reserved.
//
//正常写法
#include <cstdio>
#include <cstring>
#define MOD 1000007
int n;
int dp[50005][350];
int main()
{
while(~scanf("%d", &n))
{
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
int ans = 0;
for (int i = 1; i < 350; ++i) {
for (int j = 0; j <= n; ++j) {
if(j - i >= 0)
dp[j][i] = (dp[j-i][i] + dp[j-i][i-1]) % MOD;
}
ans = (ans + dp[n][i]) % MOD;
}
printf("%d\n", ans);
}
}
参考代码二(最优)
#include <cstdio>
#include <cstring>
#define MOD 1000007
int n;
int dp[50005][2];
int main()
{
while(~scanf("%d", &n))
{
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
int ans = 0;
for (int i = 1; i < 350; ++i) {
for (int j = 0; j < 350; ++j)//每次操作初始化
dp[j][i&1] = 0;
for (int j = 0; j <= n; ++j) {
if (j - i >= 0)
dp[j][i&1] = (dp[j - i][i&1] + dp[j - i][(i - 1)&1]) % MOD;
}
ans = (ans + dp[n][i&1]) % MOD;
}
printf("%d\n", ans);
}
}
903 AlvinZH叕掉坑里了(L)
思路
难题。本题已经超越了dp,但其本质还是dp。简化题目:将一个数拆成一个或多个数的和,即无序整数拆分问题。
无序整数拆分问题是欧拉五边形数定理的一个应用。详情请查看:分拆数 && hdu 4651 && hdu 4658。
证明五边形数定理以及证明无序拆分整数是五边形数定理的应用,这。。。就超出我的知识范围了。
参考代码
//
// Created by AlvinZH on 2017/10/23.
// Copyright (c) AlvinZH. All rights reserved.
//
#include <cstdio>
#include <cstring>
#define MaxSize 50005
#define MOD 1000007
#define f(x) (((x) * (3 * (x) - 1)) >> 1)
#define g(x) (((x) * (3 * (x) + 1)) >> 1)
using namespace std;
int n, ans[MaxSize];
void init()
{
memset(ans, 0, sizeof(ans));
ans[0] = 1;
for (int i = 1; i <= 50000; ++i) {
for (int j = 1; f(j) <= i; ++j) {
if (j & 1)
ans[i] = (ans[i] + ans[i - f(j)]) % MOD;
else
ans[i] = (ans[i] - ans[i - f(j)] + MOD) % MOD;
}
for (int j = 1; g(j) <= i; ++j) {
if (j & 1)
ans[i] = (ans[i] + ans[i - g(j)]) % MOD;
else
ans[i] = (ans[i] - ans[i - g(j)] + MOD) % MOD;
}
}
}
int main()
{
init();
while (~scanf("%d", &n))
{
printf("%d\n", ans[n]);
}
}
/*
* 欧拉五边形定理:P(n)表示n的划分种数。
* P(n) = ∑{P(n - k(3k - 1) / 2 + P(n - k(3k + 1) / 2 | k ≥ 1}
* n < 0时,P(n) = 0;n = 0时, P(n) = 1即可。
*/
916 AlvinZH不想掉坑里了(M)
分析
中等题。单源最短路径。最短路径是一个经典算法问题,所以我为其特地单独写了一篇随笔,仅供参考。
AlvinZH又来骗访客量啦:四大算法解决最短路径问题。
参考代码
//
// Created by AlvinZH on 2017/11/3.
// Copyright (c) AlvinZH. All rights reserved.
//
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int N=100010;
const int INF = 0x3f3f3f3f;
bool Vis[N];//是否被访问过
int Dis[N];//距离
struct DisAndStart
{
int dis;//距离
int start;//起点
bool operator < (const DisAndStart& p)const {
return p.dis<dis;
}
DisAndStart(int d, int s):dis(d),start(s){}
};
vector<pair<int, int> > V[N];//二维的vector数组
void dijkstra(int s)
{
priority_queue<DisAndStart> Q;
memset(Dis,INF,sizeof(Dis));
memset(Vis,0,sizeof(Vis));
Dis[s]=0;
Q.push(DisAndStart(0,s));
while(!Q.empty())
{
DisAndStart p=Q.top();
Q.pop();
if(Vis[p.start]) continue;//已经访问过该点
Vis[p.start]=1;
for(int t=0;t<V[p.start].size();t++)
{
int end=V[p.start][t].first;
int Time=V[p.start][t].second;
if(Dis[p.start]+Time<Dis[end])
{
Dis[end]=Dis[p.start]+Time;
Q.push(DisAndStart(Dis[end],end));
}
}
}
}
int main()
{
//freopen("in2.txt", "r", stdin);
//freopen("out2.txt", "w", stdout);
int n, m, k, des;
int x, y, Time;
while(~scanf("%d%d%d", &n, &m, &k))
{
for(int i = 1; i <= n; i++)//清空数据
V[i].clear();
while(m--)
{
scanf("%d%d%d", &x, &y, &Time);
V[x].push_back(make_pair(y, Time));
V[y].push_back(make_pair(x, Time));
}
dijkstra(1);
int cnt = 1;
for(int i = 0; i < k; ++i)
{
scanf("%d", &des);
if(Dis[des] == INF) printf("Case %d:-1\n", cnt);
else printf("Case %d:%d \n", cnt, Dis[des]);
cnt++;
}
printf("\n");
}
}
AlvinZH掉坑系列讲解(背包DP大作战H~M)的更多相关文章
- 851 AlvinZH的鬼畜密码(背包DP大作战N)
851 AlvinZH的鬼畜密码 思路 难题.动态规划. 先判断字符串是否合理(可翻译),然后分段处理,每一小段用动态规划求出解法数. dp[i]:字符串str[0~i]的解法数.通过判断str[i] ...
- 963 AlvinZH打怪刷经验(背包DP大作战R)
963 AlvinZH打怪刷经验 思路 这不是一道普通的01背包题.大家仔细观察数据的范围,可以发现如果按常理来的话,背包容量特别大,你也会TLE. 方法一:考虑01背包的一个常数优化----作用甚微 ...
- 976 AlvinZH想回家(背包DP大作战T)
976 AlvinZH想回家 思路 如果在第i小时有一些飞机延误,那么一架飞机的c值越大,这一小时产生的损失也越大.而使这一小时产生的损失尽可能的小并不会导致接下来时间产生的损失增大.因此应当每一小时 ...
- 977 AlvinZH过生日(背包DP大作战S)
977 AlvinZH过生日 思路 难题.逆推DP. 要明确dp的状态只与是否有选择权有关,而与选择权在谁手里无关.因为不论选择权在谁手里,那个人都会尽可能的获得最大的蛋糕重量. dp[i]表示分配到 ...
- 991 AlvinZH的奇幻猜想----整数乘积plus(背包DP大作战P)
914 AlvinZH的奇幻猜想----整数乘积puls 思路 难题.动态规划. 将数字串按字符串输入,处理起来更方便些. dp[i][j]:表示str[0~i]中插入j个乘号时的乘积最大值.状态转移 ...
- 906 AlvinZH的奇幻猜想----整数乘积(背包DP大作战O)
906 AlvinZH的奇幻猜想----整数乘积 思路 难题.动态规划. 将数字串按字符串输入,处理起来更方便些. dp[i][j]:表示str[0~i]中插入j个乘号时的乘积最大值.状态转移方程为: ...
- DP大作战—组合背包
题目描述 组合背包:有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包). DD大牛的伪代码 for i = 1 to N if 第i件物品属 ...
- DP大作战——多重背包
题目描述 在之前的上机中,零崎已经出过了01背包和完全背包,也介绍了使用-1初始化容量限定背包必须装满这种小技巧,接下来的背包问题相对有些难度,可以说是01背包和完全背包的进阶问题. 多重背包:物品可 ...
- DP大作战—状态压缩dp
题目描述 阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了.现在,零崎要在地图上 ...
随机推荐
- 16进制颜色转普通RGB
做开发的会遇到很多时候UI给到的是16进制的颜色 然而很多时候我们需要把它转换成适合我们方法的RGB参数 当然通过网页转换也可以达到目的 但是我现在选择写一个分类来解决 一劳永逸~ 1.首先说下 ...
- Github 使用的Markdown语言
简介 官方站点:http://daringfireball.net/projects/markdown/syntax 中文介绍:http://www.worldhello.net/gotgithub/ ...
- 浅谈c/c++中的指针问题
首先给出几种指针类型来作出区分,不看后面的解析如果可以自己分辨正确那么就算对指针有一个很好的掌握了,就没有必要再去看后面的解析,如果不能完全区分,那么就有必要仔细看看后面解析. 1 Char * p ...
- python 全栈基础作业题
1.执行 Python 脚本的两种方式 1..直接使用PyCharm执行 2.python run.py 调用python 解释器来调用python脚本 2.简述位.字节的关系 数据存储是以“字节”( ...
- zigbee广播通信原理
广播:可以理解成,发送模块发出数据,这个网络里的所有节点模块都可以拿到这个数据. 实验:终端模块以广播的形式发送出去,让协调器和路由器模块作为接收器收到数据并显示出来! 协调器模块作为接收模块: 和单 ...
- MySQL 存储过程和存储函数 的定义条件和处理程序
#三.定义条件和处理程序 #mysql 存储函数和过程可以将错误 变成我们想要的处理结果分2步骤 #1.定义错误条件 语法:DECLARE 条件名字 CONDITION for 错误编码 #2. 定义 ...
- Win10安装Mongodb,并配置成服务
好吧,今天突然发现新买的surface上没有安装mongodb,然后想着安装一下,顺便记录一下,虽说安装过程很简单 一:下载安装,然后拷贝到C盘根目录,这个就不多说了,比QQ都简单. 二:把bin文件 ...
- 编写高质量代码改善C#程序的157个建议——建议117:使用SSL确保通信中的数据安全
建议117:使用SSL确保通信中的数据安全 SSL(Secure Socket Layer)最初是由NetScape公司设计的,用于Web安全的网络协议.目前它已经广泛应用到各类网络传输通信中了.SS ...
- 哇,两门学考都是A(〃'▽'〃)
看来只要拼命去搞,两个月也是可以搞出来的啊~
- 12、Semantic-UI之输入框
12.1 基础输入框 在Semantic-UI中可以定义多个样式的输入框,可以将图片与输入框结合,输入提示信息文字,设置输入框的状态. 示例:定义基础输入框 用户名: <div class= ...