1,问题:

1,问题描述:

Akari 问题

Akari问题有时又被称为Light up或者Beleuchtung,源于日本逻辑解密游戏系列Nikoli,同属于Nikoli谜题的除Akari之外还有Sudoku(数独)和Kakuro(数谜)等。

游戏规则很简单。点灯游戏的棋盘是一张方形格网,其中的格子可能是黑色也可能是白色。游戏目标是在格网中放置灯泡,使之能照亮所有的白色方格。如果一个方格所在的同一行或同一列有一个灯泡,并且方格和灯泡之间没有黑色格子阻挡,那么这个方格将被灯泡照亮。同时,放置的每个灯泡不能被另一个灯泡照亮。
某些黑色格子中标有数字。这些数字表示在该格子四周相邻的格子中共有多少个灯泡。

2,题目要求:

格式说明

输入数据由若干文件组成,每个文件描述一个Akari问题的初始状态,编写程序读入此文件,根据初始状态求解。有的有一个解,有的有多个解,我们保证有解。

文件由若干行组成,第一行为两个整数 nm,代表棋盘的行数和列数。之后的 n 行每行有 m 个整数表示棋盘的每个格子的状态,若它为 -2,则表示是白格子,若它为 -1,则表示是没有数字的黑格子,若它为 0-4,则表示是数字 0-4 的黑格子。若你想把灯泡放在白色格子上面,则需要将 -2 改为 5,因为 5表示有灯泡的格子。

2,算法

2.1:algo1:

问题和算法你都可以从https://www.educoder.net/tasks/mthkqlu46583获得;

如下:

对问题进行划分
根据黑色方格中数字的大小,按从大到小的顺序进行排序,并将“在一个有数字的黑色方格周围放置‘车’”定义为一步。
选择枚举
枚举每一步的选择。
若黑色方格中的数字为4,则其相邻的周围格子的“灯泡”的放置方式为1种,即上下左右均放置一个“灯泡”。
若黑色方格中的数字为3,则其相邻的周围格子的“灯泡”的放置方式为4种,即在左右下、下右上、右上左、上左下的格子中放置“灯泡”。
若黑色方格中的数字为2,则其相邻的周围格子的“灯泡”的放置方式有6种,即在上左、上下、上右、左下、左右、下右的格子中放置“灯泡”。
若黑色方格中的数字为1,则其相邻的周围格子的“灯泡”的放置方式有4种,即在上、下、左、右的格子中放置“灯泡”。
若黑色方格中的数字为0,则其相邻的周围格子的“灯泡”的放置方式有1种,即所有周围格子均不放置车。
构造解空间
根据上述讨论构造解空间,初始状态为解空间树的根节点,从编号最大的黑色格子开始尝试填入“灯泡”,填入后判断是否为一个可行解,若为可行解,则解空间向下进行分枝,否则向上进行回溯。解空间树的结构大致如图2所示。
程序设计与实现
根据回溯法的伪代码和上述算法的设计思路,建立合适的数据模型与程序结构,编写程序求解问题,同时记录程序的运行时间。
讨论与改进
分析算法的时间负责度与空间复杂度,根据某一用例和计算机的计算能力,估计程序运行时间,并将该时间与实际运行时间进行比较。
同时讨论与优化程序结构和数据结构,以求达到更快的程序执行速度和更少的内存占用量。

2.2:algo2:

   // 根据curm的有效位来获得可以放灯的所有位置// arg1: 存放可以放灯的所有位置// arg2: 当前矩阵void getLeft(vector<POINT>& left, vector<vector<grid> > & curm){// 根据当前放入的那个灯来更新矩阵,同时检测是否可以成功更新// 不能成功更新的说名当前点不能放,curm所作的改变需要清除,则返回false然后换下一个点来回溯bool updateCurmByLight(POINT light, vector<vector<grid> > & curm) {//回溯函数void backT(vector<POINT>& left, vector<vector<grid> > & curm,\vector<vector<int> > & res){if(如果能cover住所有的位置,则将res更新,然后更新findRes){return ;}//if(当所有的位置都用了,但是没得到结果,也要回溯){return ;}for(int i=0; i<left.size() &&(!findRes); i++){auto tmpCurm= curm;auto tmpLightedUp = lightedUp;int tmpDarkSum=darkSum;auto tmpleft = left;if(left.size() >= 15){cout<<"  left len: "<<left.size()<<endl;}if(updateCurmByLight(left[i], curm)){ //可以正确更新,并且内容已经被更新//更新剩余,放入该灯,接着回溯getLeft(left, curm);backT(left, curm, res);}//当该点的回溯退出来了,我们需要回滚到进入之前,然后进入到下一个遍历;curm = tmpCurm;darkSum = tmpDarkSum;lightedUp = tmpLightedUp;left = tmpleft;}}vector<vector<int> > solveAkari(vector<vector<int> > & g){//存放结果vector<vector<int> > res(n, vector<int>(m, 0));//初始化你的可以放灯的位置 调用函数: getLeftgetLeft(left, curm);//回溯获得结果backT(left, curm, res);return res;}
}

第二种是自己写的,算法是每次放一个灯,而第一种是每次放一个黑格子周围的灯们(比如黑格子数字为3,则有4中放法,是这样去遍历回溯的)

3,解答代码

这里的解答代码很详细,但是采用的是算法中的第2种,可以直接阅读,注释很足;

//
// Created by cxy on 19-7-22.
//
# include <bits/stdc++.h>
# include "akari.h"
using namespace std;/**
输入数据由若干文件组成,每个文件描述一个Akari问题的初始状态,编写程序读入此文件,
根据初始状态求解。有的有一个解,有的有多个解,我们保证有解。文件由若干行组成,第一行为两个整数 n,m,代表棋盘的行数和列数。
之后的 n 行每行有 m 个整数表示棋盘的每个格子的状态,若它为 -2,则表示是白格子,
若它为 -1,则表示是没有数字的黑格子,
若它为 0-4,则表示是数字 0-4 的黑格子。
若你想把灯泡放在白色格子上面,则需要将 -2 改为 5,因为 5 表示有灯泡的格子。你需要在右侧代码编辑框给出的函数中编写你的代码,函数的参数为我们给出的light up矩阵,
你需要在该函数中返回相同大小的结果矩阵。对于有多个解的light up,你可以返回其中的
任意一组解,我们将对你返回的矩阵进行检查,若结果正确,提示The answer is right!,
否则提示其它。*/namespace aka{
//请在命名空间内编写代码,否则后果自负//用以记录灯的位置typedef struct{int x = 0;int y = 0;int val = -2;}POINT;//为棋盘里的每个格子加一个标志位typedef struct{int value = 0;bool valid = true;}grid;//找到结果的标志bool findRes = false;//没有被照亮的总数int darkSum = 0;//黑色格子的坐标vector<POINT> bs;//n行m列int n = 0, m = 0;//标记矩阵: 白格子是否在黑格子周围,是白格子并且在黑格子周围,则为true,否则为falsevector<vector<bool> >aroundBlack;//存放: 在黑点周围的格子围绕的黑点的数值;vector<vector<int> >aroundBlackValue;//获得剩余的灯的时候按照围绕的黑格子的数字从高到低排列;bool cmp(POINT a, POINT b){return a.val > b.val;}
//    struct {
//        bool operator()(int a, int b) const
//        {
//            return a < b;
//        }
//    } customLess;//表记是否被照亮vector<vector<bool> >lightedUp;void display(vector<vector<grid> > & ans){printf("your magic matrix--------------------------------> \n");int n = ans.size(), m = ans[0].size();for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {printf("%4d", ans[i][j].value);}printf("\n");}printf("your valid matrix \n");for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {printf("%4d", ans[i][j].valid);}printf("\n");}//        printf("your aroundBlack \n");
//
//        for (int i = 0; i < n; ++i) {
//            for (int j = 0; j < m; ++j) {
//                printf("%4d", aroundBlack[i][j]?1:0);
//            }
//            printf("\n");
//        }}void pv(vector<POINT> a){printf("left is \n");for (int j = 0; j < a.size(); ++j) {printf("%4d", a[j].x);}printf("\n");for (int j = 0; j < a.size(); ++j) {printf("%4d", a[j].y);}printf("\n");for (int j = 0; j < a.size(); ++j) {printf("%4d", a[j].val);}printf("\n");}void pv1(vector<vector<int> > a){printf("around black 's value is \n");for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {printf("%4d", a[i][j]);}printf("\n");}}void pv2(vector<vector<bool> > a){printf("lightedUp is \n");for (int i = 0; i < n; ++i) {for (int j = 0; j < m; ++j) {printf("%4d", a[i][j]?1:0);}printf("\n");}}// 根据curm的有效位来获得可以放灯的所有位置// arg1: 存放可以放灯的所有位置// arg2: 当前矩阵void getLeft(vector<POINT>& left, vector<vector<grid> > & curm){//扫描矩阵, ,需要先把格子周围的点放入left的前面,// 不在黑格子周围的放在后面,以保证每次回溯总是从黑格子周围开始;left.clear();for(int i=0; i<n; i++){for(int j=0; j<m; j++){POINT tmp;if(curm[i][j].valid){ //说明当前格子有效tmp.x = i;tmp.y = j;//接下来要区分它是不是黑格子周围的if(aroundBlack[i][j]){ //从头放入//该可以用点周围的黑色灯的值tmp.val = aroundBlackValue[i][j];left.emplace(left.begin(), tmp);}else{ //从尾巴放入left.push_back(tmp);}}}}sort(left.begin(), left.end(), cmp);}//设置i,j处的点,要是为0,将其i周围置为falsevoid setAround0(int i,  int j, vector<vector<grid> > & curm){if(curm[i][j].value == 0){if(i==0){if(j==0){curm[i+1][j].valid = false;curm[i][j+1].valid = false;}else if(j==m-1){curm[i][j-1].valid = false;curm[i+1][j].valid = false;}else{curm[i][j+1].valid = false;curm[i][j-1].valid = false;curm[i+1][j].valid = false;}}else if(i==n-1){if(j==0){curm[i-1][j].valid = false;curm[i][j+1].valid = false;}else if(j==m-1){curm[i-1][j].valid = false;curm[i][j-1].valid = false;}else{curm[i-1][j].valid = false;curm[i][j+1].valid = false;curm[i][j-1].valid = false;}}else{if(j==0){curm[i][j+1].valid = false;curm[i-1][j].valid = false;curm[i+1][j].valid = false;}else if(j==m-1){curm[i][j-1].valid = false;curm[i-1][j].valid = false;curm[i+1][j].valid = false;}else{curm[i+1][j].valid = false;curm[i][j+1].valid = false;curm[i-1][j].valid = false;curm[i][j-1].valid = false;}}}}// 根据当前放入的那个灯来更新矩阵,同时检测是否可以成功更新// 不能成功更新的说名当前点不能放,curm所作的改变需要清除,则返回false然后换下一个点来回溯bool updateCurmByLight(POINT light, vector<vector<grid> > & curm) {int x0 = light.x, y0= light.y;//判断当前点是否有效if(!curm[x0][y0].valid){return false;}//放入该灯,当然本身也需要算被照亮,可以只darkSum-1:curm[x0][y0].value = 5;curm[x0][y0].valid = false;darkSum--;//放入灯以后,该处周围的黑格子的数字需要减少,并且查看是否有为零的情况,为0的话需要将其周围视作不可用vector<POINT> blacks;if(y0 >= 1 && (1<=curm[x0][y0-1].value && 4>=curm[x0][y0-1].value)){curm[x0][y0-1].value --;setAround0(x0, y0-1, curm);}if(x0 >= 1 && (1<=curm[x0-1][y0].value && 4>=curm[x0-1][y0].value)){curm[x0-1][y0].value --;setAround0(x0-1, y0, curm);}if(y0 <= n-2 && (1<=curm[x0][y0+1].value && 4>=curm[x0][y0+1].value)){curm[x0][y0+1].value --;setAround0(x0, y0+1, curm);}if(x0 <= m-2 && (1<=curm[x0+1][y0].value && 4>=curm[x0+1][y0].value)){curm[x0+1][y0].value --;setAround0(x0+1, y0, curm);}//分别从该灯的+x,-x,+y,-y方向更新被照亮的地方,也就是将其置为fasleint xp=light.x, xn=xp;int yp=light.y, yn=yp;//curm 为黑色格子的方式为-1到4,5是灯,所以只要当前格子值不是-2,就需要停止//而且当为5的时候需要返回false,当遇到[-1, 4]之间的数据就停止探索;//x正方向for(int i=xp+1; i<m ;i++){if(-1<=curm[i][y0].value && 4>=curm[i][y0].value){break;}else if(curm[i][y0].value == 5){return false;}else{//被照亮 若是i没有被照亮,那么就将darkSum减1if(!lightedUp[i][y0]){curm[i][y0].valid = false;darkSum--;lightedUp[i][y0] = true;}}}//x负方向for(int i=xp-1; i>=0 ;i--){if(-1<=curm[i][y0].value && 4>=curm[i][y0].value){break;}else if(curm[i][y0].value == 5){return false;}else{//被照亮 若是i没有被照亮,那么就将darkSum减1if(!lightedUp[i][y0]){curm[i][y0].valid = false;darkSum--;lightedUp[i][y0] = true;}}}//y正方向for(int i=yp+1; i<n ;i++){if(-1<=curm[x0][i].value && 4>=curm[x0][i].value){break;}else if(curm[x0][i].value == 5){return false;}else{//若是i没有被照亮,那么就将darkSum减1, 同时置valid和照亮居正if(!lightedUp[x0][i]){curm[x0][i].valid = false;darkSum--;lightedUp[x0][i] = true;}}}//y负方向for(int i=yn-1; i>=0 ;i--){if(-1<=curm[x0][i].value && 4>=curm[x0][i].value){break;}else if(curm[x0][i].value == 5){return false;}else{//若是i没有被照亮,那么就将darkSum减1, 同时置valid和照亮居正if(!lightedUp[x0][i]){curm[x0][i].valid = false;darkSum--;lightedUp[x0][i] = true;}}}return true;}//回溯函数void backT(vector<POINT>& left, vector<vector<grid> > & curm,\vector<vector<int> > & res){//返回触发条件://1,失败放入,在update的时候就解决了// 也就是说,update完成后,会决定这个点是放入还是不放入,你不需要关心//2,找到了解答//如果发现当前的灯们的顶点(也就是最近放入的一个灯)不能放入,则直接返回//如果能cover住所有的位置,则将res更新,然后更新findResif(darkSum == 0){bool satisfy = true;//如果不能满足所有黑色格子上的数字都变为0for(int i=0; i<bs.size(); i++){satisfy = satisfy && (curm[bs[i].x][bs[i].y].value == 0);}//那就返回if(!satisfy){return ;}for(int i=0; i<n; i++){for(int j=0; j<m; j++){res[i][j] = curm[i][j].value;}}findRes = true;exit(0);return ;}//当所有的位置都用了,但是没得到结果,也要回溯if(left.empty()){
//            cout <<endl<<endl<< "backTrack to last backT's next loop"<<endl<<endl;return ;}//在调用backT后,记得把left,lights和curm退回到押入之前的状态//这个left是在你选定了一个黑格子作为起点,把它周围的点放到left的最前面,// 相当于你这个for循环只是在遍历l以该黑格子周围放灯作为起点,就可以得到最终结果// 所以初始化left的时候,需要先把黑格子周围的点放入left的前面,不在黑格子周围的放在后面,以保证每次回溯总是从前面开始;
#pragma omp parallel forfor(int i=0; i<left.size() &&(!findRes); i++){auto tmpCurm= curm;auto tmpLightedUp = lightedUp;int tmpDarkSum=darkSum;auto tmpleft = left;//>>>>>>>>>>>>>打印调试信息>>>>>>>>>>>>>>>>
//            display(curm);
//            pv(left);
//            pv2(lightedUp);
//            cout<<"--------dark: "<<darkSum<<" | ready to using x:"<<left[i].x<<", y: "<<left[i].y<<"  left len: "<<left.size()<<endl;if(left.size() >= 15){cout<<"  left len: "<<left.size()<<endl;}if(updateCurmByLight(left[i], curm)){ //可以正确更新,并且内容已经被更新//更新剩余,放入该灯,接着回溯getLeft(left, curm);backT(left, curm, res);}//当该点的回溯退出来了,我们需要回滚到进入之前,然后进入到下一个遍历;curm = tmpCurm;darkSum = tmpDarkSum;lightedUp = tmpLightedUp;left = tmpleft;}}vector<vector<int> > solveAkari(vector<vector<int> > & g){// 请在此函数内返回最后求得的结果//获得n行m列n = g.size();m = g[0].size();//根据当前矩阵获得的剩下可以使用的灯vector<POINT> left(0);//根据回溯法一步步改变的当前矩阵vector<vector<grid> > curm(0);//下一步,初始化这个ABlack,然后将其赋值给aroundBlack即可//标记矩阵: 白格子是否在黑格子周围,是白格子并且在黑格子周围,则为true,否则为false//点亮矩阵: lightUp标记该格子是否被照亮vector<vector<bool> > ABlack(n, vector<bool>(m, false));vector<vector<int> > ABlackValue(n, vector<int>(m, false));vector<vector<bool> > LUp(n, vector<bool>(m, false));//初始化当前灯的矩阵和每个位置上的有效位,顺便初始化darkSum,顺便获得aroundBlack的值for(int i=0; i<n; i++) {curm.emplace_back(vector<grid>(m));}for(int i=0; i<n; i++){for(int j=0; j<m; j++){curm[i][j].value = g[i][j];if(g[i][j] != -2){  //说明是黑色格子,标记周围的白格子,他们是在黑色周围,标记数字为0的黑格子的周围无效//将自己置为faslecurm[i][j].valid = false;//需要将数字为0的黑格子周围的点置为falsesetAround0(i, j, curm);//标记自己周围的格子为aroundBlackif(i==0){if(j==0){ABlack[i+1][j] = true;ABlack[i][j+1] = true;ABlackValue[i+1][j] = curm[i][j].value;ABlackValue[i][j+1] = curm[i][j].value;}else if(j==m-1){ABlack[i][j-1] = true;ABlack[i+1][j] = true;ABlackValue[i][j-1] = curm[i][j].value;ABlackValue[i+1][j] = curm[i][j].value;}else{ABlack[i][j+1] = true;ABlack[i][j-1] = true;ABlack[i+1][j] = true;ABlackValue[i][j+1] = curm[i][j].value;ABlackValue[i][j-1] = curm[i][j].value;ABlackValue[i+1][j] = curm[i][j].value;}}else if(i==n-1){if(j==0){ABlack[i-1][j] = true;ABlack[i][j+1] = true;ABlackValue[i][j+1] = curm[i][j].value;ABlackValue[i-1][j] = curm[i][j].value;}else if(j==m-1){ABlack[i-1][j] = true;ABlack[i][j-1] = true;ABlackValue[i-1][j] = curm[i][j].value;ABlackValue[i][j-1] = curm[i][j].value;}else{ABlack[i-1][j] = true;ABlack[i][j+1] = true;ABlack[i][j-1] = true;ABlackValue[i-1][j] = curm[i][j].value;ABlackValue[i][j+1] = curm[i][j].value;ABlackValue[i][j-1] = curm[i][j].value;}}else{if(j==0){ABlack[i][j+1] = true;ABlack[i-1][j] = true;ABlack[i+1][j] = true;ABlackValue[i][j+1] = curm[i][j].value;ABlackValue[i-1][j] = curm[i][j].value;ABlackValue[i+1][j] = curm[i][j].value;}else if(j==m-1){ABlack[i][j-1] = true;ABlack[i-1][j] = true;ABlack[i+1][j] = true;ABlackValue[i][j-1] = curm[i][j].value;ABlackValue[i-1][j] = curm[i][j].value;ABlackValue[i+1][j] = curm[i][j].value;}else{ABlack[i+1][j] = true;ABlack[i][j+1] = true;ABlack[i-1][j] = true;ABlack[i][j-1] = true;ABlackValue[i][j-1] = curm[i][j].value;ABlackValue[i][j+1] = curm[i][j].value;ABlackValue[i+1][j] = curm[i][j].value;ABlackValue[i-1][j] = curm[i][j].value;}}}else{ //说明是白格子,一开始当然没有被照亮darkSum ++;LUp[i][j] = false;}}}aroundBlack = ABlack;aroundBlackValue = ABlackValue;lightedUp = LUp;//获得初始的bsfor(int i=0; i<n; i++){for(int j=0; j<m; j++){if(1<=curm[i][j].value && 4>=curm[i][j].value){POINT tmp;tmp.x = i; tmp.y = j;bs.emplace_back(tmp);}}}//>>>>>>>>>>>>>打印调试信息>>>>>>>>>>>>>>>>
//            display(curm);
//            pv(left);pv2(aroundBlack);pv1(aroundBlackValue);cout<<"-----------------------------";//初始化你的可以放灯的位置 调用函数: getLeft//存放结果vector<vector<int> > res(n, vector<int>(m, 0));//调用backT函数获得结果getLeft(left, curm);//通过并行的优化,就是在这里,我们通过每一个可以开始的节点来分别开启线程,这样做时间应该会快一些;backT(left, curm, res);//由于这res里面的数字为1,到4的灯在寻找答案的时候都被毁掉了,所以现在做一个恢复:for(int i=0; i<n; i++){for(int j=0; j<m; j++){if(1<=g[i][j] && 4>=g[i][j]){res[i][j] = g[i][j];}}}return res;}
}//问题:
//darksum的更新被重复了,也就是当//问题:
//需要有一个变量,记录全局的黑色格子边上剩余的个数,要是不为0,那么即使获得答案也不被认可//现在是在剩余黑格子旁边可以使用的总数非零的情况下获得答案,显然是不行的;//获得所有的黑点的points,去扫描直到所有都为0,
// 采用abNum 不能判断是否满足了所有的黑点周围都有正确的点

Akari问题详细解答相关推荐

  1. pandas.get_dummies函数用法详细解答(实践)

    pandas.get_dummies函数用法详细解答(实践) pandas.get_dummies函数用法详细解答(实践)_skywf的博客-CSDN博客 one-hot encoding one-h ...

  2. 校招社招必备核心前端面试问题与详细解答

    本文总结了前端老司机经常问题的一些问题并结合个人总结给出了比较详尽的答案.网易阿里腾讯校招社招必备知识点. 原理讲解参考:前端增长-重新定义大前端 在线课程:网易云课堂课程      思否课堂 官方博 ...

  3. 2021年 第13届 全国大学生数学竞赛 初赛(非数学类)试题详细解答

    [2020年第12届全国大学生数学竞赛--资源分享 ][1~11届省赛决赛考题及题解(数学类.非数学类).推荐学习网址.复习备考书籍推荐] 2019年 第11届 全国大学生数学竞赛 初赛(非数学类)试 ...

  4. c语言加法结合性,C语言 运算符 的结合性 怎么理解?求举例子详细解答!!

    C语言 运算符 的结合性 怎么理解?求举例子详细解答!! 关注:284  答案:5  信息版本:手机版 解决时间 2019-01-11 21:03 战魂 2019-01-11 10:01 C语言 运算 ...

  5. Linux 170个常见问题的详细解答

    Linux 170个常见问题的详细解答   <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:offi ...

  6. 操作系统课设详细解答

    操作系统课设详细解答 一.题目一 实验一 Windows 进程管理 二.实验目的 (1)学会使用 VC 编写基本的 Win32 Consol Application(控制台应用程序). (2)通过创建 ...

  7. 「 最新大厂常考架构技术面试题 + 详细解答」

    很多没有收到offer的朋友一直在 后台问我,怎么梳理面试要考的知识点.这里必须要和大家再强调一下要准备的7大方面!总结起来包括:JAVA编程语言+数据结构和算法题+计网+操作系统+设计模式+数据库+ ...

  8. 【机试题】2014大疆嵌入式笔试题(附超详细解答,下篇)

    上一篇主要是对<2014大疆嵌入式笔试题>的前一部分进行了解答,本文主要是对接下来的几道题进行解答.想要参考上一篇的点击链接:[机试题]2014大疆嵌入式笔试题(附超详细解答,上篇). 嵌 ...

  9. E - Obstacle Course的详细解答

    E - Obstacle Course的详细解答 You are working on the team assisting with programming for the Mars rover. ...

最新文章

  1. C语言实现简单线程池(转-Newerth)
  2. java 调用cpp_java jni 调用cpp文件中的方法 | 学步园
  3. 【图文详解】如何彻底删除JDK(以win10、jdk1.8为例)
  4. 优雅的在终端中编写Python
  5. (树莓派、Arduino、物联网、智能家居、机器人)传感器、机械装置、电子元件
  6. opensuse 11.2/11.3安装vmware server 1.0.10笔记
  7. 《疯狂的程序员》绝影新闻
  8. Android取手机号码
  9. 过程能力指数Cp与Cpk计算公式
  10. iphone个系列尺寸_iphone12哪个尺寸好 iphone12系列尺寸参数对比
  11. m1的docker-compose
  12. 基于TILE-GX实现快速数据包处理框架-netlib实现分析
  13. 四足机器人——12自由度舵机狗DIY(二)
  14. Event的三个阶段:CAPTURING_PHASE,AT_TARGET,BUBBLING_PHASE
  15. PHP curl--电信手机号码话费余额
  16. 【转载】抽象语法树简介(有图)
  17. C++大学教程(第二版)c++how to program Second Edition --电子工业出版社【美】harvey M.Deitel and paul James Deitel(更新中)
  18. Go语言实现A disguised sequence (I)
  19. 异地数据库同步解决方案
  20. matlab中的help怎么使用?

热门文章

  1. 区块链开发(五)区块链ICO:互联网进化的驱动力
  2. python 源代码 macd双底 高 低_久其软件怎么样MACD指标的双底形态特征详解
  3. 微信小程序上传图片后 开发者工具自动刷新问题
  4. P2178 [NOI2015] 品酒大会(并查集+后缀数组)
  5. python打印pdf特定页面_使用Python自由切分pdf文件提取任意页面
  6. Mac中从pdf文件中提取指定页的方法
  7. python编程技术解决英语单词测试(包括添加英文单词、查询英文单词和查询英文单词)以及绘制雷达图功能
  8. 使用wait函数获取子进程终止状态
  9. 关于word2016保存失败
  10. 一生一代一双人:我与51CTO学院的情缘----写于51CTO学院2周年庆