最近一直在刷动态规划的题目,深感动态规划的难度。于是复习一下最近刷的题,加深记忆。
关于什么是动态规划,可以去看百度文库的解释https://baike.baidu.com/item/动态规划/529408,不过说的十分混乱,难以理解。也可以去看看维基百科的解释https://zh.wikipedia.org/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92。

做了这么多的题目,大致的思路是建立合适的容器存放数据,寻找最优子结构,编码。
//建立容器,初始化容器,依据最优子结构循环产生数据,输出结构

闲话少叙——上题目/******************************************************************************/
例题1:硬币问题,现在有1,3,5面值的硬币无限数量。给定金额x,求使用最少的硬币组合出x元。分别求出总硬币数量,硬币使用个数。
思考:如果m[x]表示x元需要的硬币个数,m[x] = min{m[x-1]+1 ; m[x-3]+1 ; m[x-5]+1} ;
因为要求使用的各个硬币个数,还要建立一个node节点来记录,采用备忘录方法回求解。typedef struct {int nCoin; //使用硬币数量//以下两个成员是为了便于构造出求解过程的展示int lastSum;//上一个状态int addCoin;//从上一个状态达到当前状态所用的硬币种类
} state; int main()
{//用户输入总额int total;cin >> total ;//建立动态规划的容器state *m = new state[total+1];//初始化数据for(int i=0;i<=total;i++) m[i].nCoin = total;m[0].nCoin = 0;m[0].lastSum = 0;//初始化数据——准备硬币和0,1,2之间的对应关系int n =  3 ;int * coin = new int[3];coin[0] = 1;coin[1] = 3;coin[2] = 5; //循环求解-外层循环之后,需要比较三次才能知道答案,也使用了循环。for(int i=1;i<=total;i++)for(int j=0;j<n;j++)if(i-coin[j]>=0 && m[i-coin[j]].nCoin+1 < m[i].nCoin){m[i].nCoin = m[i-coin[j]].nCoin+1;m[i].lastSum = j;m[i].addCoin = coin[j];}//根据内容回推解。int i =  total; while(i > 0){cout << "使用" << m[i].addCoin << "一次" << endl;i = i- coin[m[i].lastSum]; }     return 0;} 很简单的题目,最优子结构很容易就想到了,不过很适合做第一个练习,去熟悉和了解动态规划。/******************************************************************************/
例题2:苹果装配问题,把一个区域分成n*m个小区域,其中每个区域有一定数量的苹果,设左上角为0,0,右下角为n-1,m-1.从0,0开始出发,每经过一个区域,就把该区域的苹果全部收走,求一条路径使得收获的苹果最多。
思考:刚才做了一个动态规划的题目,应该知道现在需要去寻找最优子结构。这题应该使用一个二维数组来存放数据,设为v[m+1][n+1].
v[i][j]表示的含义是到达i行j列可以获得的苹果数量。v[i][j] = max{v[i-1][j]+A[i][j] ; v[i][j-1]+A[i][j]};(A[i][j]表示第i行第j列苹果个数)。
class Node{
public:int numOfApple;int lastOperation_x;int lastOperation_y;Node(){numOfApple = 10000;lastOperation_x = 0;lastOperation_y = 0;}
} ;int main()
{//准备数据,建立一个3*4的区域//numApple表示数据信息是一个二维数组。类型是intvector<vector <int > > numApple;Node node[3][4];//循环求出解,初始化数据也放在其中for(int x = 0 ; x < 3; x++ ){for(int y = 0; y < 4;y++){//第一个数据 if(x == 0 && y ==0){node[x][y].numOfApple = numApple[x][y];continue;}if(x == 0){node[x][y].numOfApple = node[x][y-1].numOfApple + numApple[x][y] ;node[x][y].lastOperation_y = 1;//表示向前移动 continue;} if(y == 0){node[x][y].numOfApple = node[x-1][y].numOfApple + numApple[x][y] ;node[x][y].lastOperation_x = 1;//表示向后移动。 continue;} if(node[x][y-1].numOfApple > node[x-1][y].numOfApple){node[x][y].numOfApple = node[x][y-1].numOfApple + numApple[x][y] ;node[x][y].lastOperation_y = 1;//表示向前移动
            } else{node[x][y].numOfApple = node[x-1][y].numOfApple + numApple[x][y] ;node[x][y].lastOperation_x = 1;//表示向后移动。
            }    }    }//输出求出的数据cout << "一共可以有" <<node[2][3].numOfApple <<endl; //也可以通过节点的信息,求出解的过程。return 0;
}这个题目应该比较容易理解,这是最简单的动态规划。下面还有一些题目,如果难度大的题目做不出来可以拿下面的几题提高自信心。lintcode相似的题目:110. 最小路径和  https://www.lintcode.com/problem/minimum-path-sum/description
114. 不同的路径  https://www.lintcode.com/problem/unique-paths/description
115. 不同的路径 II https://www.lintcode.com/problem/unique-paths-ii/description/******************************************************************************/
例题3:装配调度问题。(如果描述的不清楚可以百度看看详细的题目)
一个公司有两条生产线,每个生产线有6个生产工序,各个生产线的相同生产工序时间不同,
从一个生产线的一个工序生产之后可以继续在该生产线上生产,也可以在另一个生产线上胜场。
相同的生产线工序移动不需要时间,不同之间需要时间,求最短的时间。
需要的时间按照顺序是:从外界装配到生产线i1,生产线A1工序花费v1,从A1到A2不需要花费,但是如果切换到B2生产就需要时间x1,A2的工序花费为v2.....最后从生产线上下来,也需要o1时间。
思考:题目很复杂,但是原理很简单,化简出来就是两条生产线,每条生产线上有若干个工序,每个工序花费一定的时间。不同的生产线花费的时间是不一样的。如果在一个生产线上从一个工序到另一个工序不需要时间,如果切换到别的生产线上需要时间。求最短的时间?
设计一个容器m[x][2],x表示一共有多少工序。m[i][j]含义是第i个工序,第j个生产线需要的时间。
不难得知m[i][0] = min{m[i-1][0]+A[i];m[i-1][1]+C[i]+A[i]},这个公式是用来计算第一行数据的,如果是第二行则为m[i][1] = min{m[i-1][1]+A[i];m[i-1][0]+C[i]+A[i]},其中A[i]表示第i个工序的时间,C[i]表示切换需要的时间。代码如下:
//用来回推最优解
class station
{public :int curTime;//当前站点已经消耗的时间int lastQueue;//上一次的队列。
    station(){curTime = 10000;lastQueue = 0;    }
};int main()
{//准备数据,这是一个具有6个工序的两个生产线。int statTime[2][6] = {7,9,3,4,8,7,812,5,6,4,5,9};int charge1Time[5] = {2,3,1,3,4};int charge2Time[5] = {2,1,2,2,1};int in1 = 2;int in2 = 4;int out1 = 3;int out2 = 2;//建立容器station stat[2][6];int i ;int j ;//循环求每一个数据位置的解for(j = 0 ; j < 6 ; j ++){for(i = 0 ; i < 2;i++){//如果是第一个的话 if(j == 0){stat[i][j].curTime = statTime[i][j];continue;}//求当前在第一条生产线上 if(i%2 == 0){//第一行 if(stat[i][j-1].curTime > stat[i+1][j-1].curTime+charge2Time[j-1]){//需要换行stat[i][j].curTime = stat[i+1][j-1].curTime+charge2Time[j-1]+statTime[i][j];stat[i][j].lastQueue = 2; }else{//不需要换行 stat[i][j].curTime = stat[i][j-1].curTime+statTime[i][j];stat[i][j].lastQueue = 1; }} else{//在第二行 if(stat[i][j-1].curTime > stat[i-1][j-1].curTime+charge1Time[j-1]){//需要换行stat[i][j].curTime = stat[i-1][j-1].curTime+charge1Time[j-1]+statTime[i][j];stat[i][j].lastQueue = 1; }else{//不需要换行 stat[i][j].curTime = stat[i][j-1].curTime+statTime[i][j];stat[i][j].lastQueue = 2; }} }}cout << stat[0][5].curTime<<endl;cout << stat[1][5].curTime <<endl;
} 装配问题思路并不是很复杂,应该还是很容易想到的。/******************************************************************************/
例题4:给出两个单词word1和word2,计算出将word1 转换为word2的最少操作次数。你总共三种操作方法:插入一个字符删除一个字符替换一个字符
分析:这个题目是处理两个字符串相关问题的。一般字符串相关的算法都是使用动态规划。
建立一个容器m[len1][len2],其中len1和len2分别表示单词的长度。m[i][j]表示如果第一个单词取前面的i个第二个单词取后面的j个需要调整的次数。
如果m[i][j]插入一个数据,m[i][j] = m[i][j-1]+1。
如果m[i][j]删除一个数据,m[i][j] = m[i-1][j]+1.
如果m[i][j]中有一个字符相等,则有m[i][j] = m[i-1][j-1](+1如果是替换需要增加1)
通过这些从上面的数据中找到最小的就可以了。m[i][j] = min{m[i-1][j-1] + 0/1,m[i-1][j]+1,m[i][j-1]+1 }代码如下:
//记录最优解的信息。
class memo{
public:int time;//这个节点的次数int lastOpt;//上一个操作是0修改,1插入,2删除。
    memo(){time = 0 ; lastOpt = 0;}
};class Solution {
public:int match(char d,char s){if(d == s){return 0; //如果相等返回0
        }    else{return 1;} } int minDistance(string &word1, string &word2) {//准备数据,动态建立一个二维数组,记着使用delete删除空间哦int len_1 = word1.length();int len_2 = word2.length(); memo ** m = new memo*[len_2+1];for(int i = 0 ; i < len_2+1 ; i++) {m[i] = new memo[len_1+1];}//对边缘经行初始化for(int i = 0 ; i < len_2+1 ; i++){//如果B有i个数据,A没有数据,需要做的调整就只有插入, m[i][0].time = i;}for(int j = 0 ; j < len_1+1; j++){//如果B中没有数据,A中数据,需要做的调整就是删除。 m[0][j].time = j; } //循环求出每一个数据的值int i ,j;for(i = 1 ; i < len_2+1; i++){for(j = 1 ;j < len_1+1; j++){//计算3中情况 int way1 = m[i-1][j-1].time + this->match(word2[i-1],word1[j-1]); //判断最后一个是否相同的。 int way2 = m[i-1][j].time+1;int way3 = m[i][j-1].time+1;//取其中的最小值。if(way1 > way2){if(way2 > way3){m[i][j].time = way3;m[i][j].lastOpt = 3;        }        else{m[i][j].time = way2;    m[i][j].lastOpt = 2;}}else{if(way1 > way3){m[i][j].time = way3;m[i][j].lastOpt = 3;        }        else{m[i][j].time  = way1;m[i][j].lastOpt = 1;    }}    }} //输出数据cout << "需要调整的次数:" << m[len_2][len_1].time <<endl;int ret = m[len_2][len_1].time;delete [] m;return ret;}
};//这是lintcode上面的一个题目,是学习动态规划路上看着代码分析的。下面几个题目都是字符串相关的动态规划问题。/******************************************************************************/
例题5:给出三个字符串:s1、s2、s3,判断s3是否由s1和s2交叉构成。例如:比如 s1 = "aabcc" s2 = "dbbca";当 s3 = "aadbbbaccc", 返回 false.当 s3 = "aadbbcbcac",返回  true.思路:这个题目我使用了两种方法来实现,第一中使用回溯法,判断s3中的数据是s1的还是s2的,如果都是就记录一下,如果都不是就返回记录的点。第二种是动态规划:之前需要建立容器bool m[len1][len2]其中len1表示s1的长度,len2表示len2的长度。因为s3的长度一定是s1和s2的长度之和,
所以m[i][j]表示的内容是如果s1区长度i,s2取长度j,则s3也应该取i+j的长度。
则有m[i][j] = m[i][j-1] && s1[i] == s2[j] || m[i-1][j] && s1[i] == s2[j]代码如下:
class Solution {
public:bool isInterleave(string &s1, string &s2, string &s3) {//建立一个i+1和j+1的数组if(s1.length() + s2.length() != s3.length()){return false;}bool ** m = new bool*[s2.length()+1];for(int i = 0;i<s2.length()+1;i++){m[i] = new bool [s1.length()+1];}    //初始化数据//如果B中没有数据,只有A中有数据
            m[0][0] = true; for(int i = 1 ; i < s1.length()+1;i++){//如何判断是否是true//如果前面是true ,而且现在也是相等的 m[0][i] = m[0][i-1] && s1.at(i-1) == s3.at(i-1); } for(int i = 1 ; i < s2.length()+1;i++){//如何判断是否是true//如果前面是true ,而且现在也是相等的 m[i][0] = m[i-1][0] && s2.at(i-1) == s3.at(i-1); } for(int i = 1;i < s2.length()+1;i++){for(int j = 1 ; j < s1.length()+1;j++){//默认情况下m[i][j] = false;//如果s1[i]和s3[i+j] 相等,而且m[i-1][j] == true;//如果s1[j]和s3[i+j] 相等,而且m[i][j-1] ==true; if(s1[j-1] == s3[i+j-1]){m[i][j] = m[i][j-1] ;    } if(s2[i-1] == s3[i+j-1]){m[i][j] = m[i][j] || m[i-1][j] ;    }     }}return m[s2.length()][s1.length()];}
};/******************************************************************************/
例题6:最长公共子序列  lintcode:77题
给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。
给出"ABCD" 和 "EDCA",这个LCS是 "A" (或 D或C),返回1
给出 "ABCD" 和 "EACB",这个LCS是"AC"返回 2思考:给定两个字符串,返回最长的公共子序列的长度。因为是两个字符串,很容易的想到采用一个二维数组来记录问题的解。
定义一个变量m[len1][len2],其中len1表示s1的长度,len2表示len2的长度。值m[i][j]表示的含义是如果s1取i个,s2取j个,他们的公共子序列的长度。m[i][j] =  if(s1[i] == s[j]) {m[i-1][j-1]} else {min{m[i-1][j},m[i][j-1]}}代码如下:
class Solution {
public:int longestCommonSubsequence(string &A, string &B) {//建立一个容器用来存放数据int **m = new int* [A.length()+1];for(int i = 0 ; i < A.length()+1;i++){m[i] = new     int [B.length()+1];}//初始化数据m[0][0] = 0;for(int i = 0 ; i < A.length()+1;i++){m[i][0] = 0;    } for(int i = 0 ; i < B.length()+1;i++){m[0][i] = 0;    } //循环处理数据for(int i = 1 ; i < A.length()+1;i++){for(int j = 1 ; j < B.length()+1;j++){//涉及2个结果需要比较//仅仅需要比较一侧就可以了 //针对两个条件进行判断if(A.at(i-1) == B.at(j-1)) {m[i][j] = m[i-1][j-1] + 1;}else{if(m[i][j-1] < m[i-1][j])    {m[i][j]    = m[i-1][j];}else{m[i][j] = m[i][j-1];}}}} //cout << m[A.length()][B.length()];return m[A.length()][B.length()];}
};/******************************************************************************/
例题7:最长上升子序列 lintcode:76题
给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度。
给出 [5,4,1,2,3],LIS 是 [1,2,3],返回 3
给出 [4,2,4,5,3,7],LIS 是 [2,4,5,7],返回 4思路:这个题目和以往的题目都不同,以往都是字符串,而且一般都是两个,很容易就想到要设置m[i][j]这样的容器。这个题目只有一个序列,采用什么容器,最优子结构是什么都比较困难。
看了答案之后,才知道这个题目只需要一维数组就可以了,m[len+1],其中len+1表示序列的长度,m[i]表示的值就是只取前面的i
个数据,最长的长度。
m[i] = max{if(a[i] > a[k]) m[k] + 1}//其中k是0~i-1的整数。
代码如下:
class Solution {
public:/*** @param nums: An integer array* @return: The length of LIS (longest increasing subsequence)*/int longestIncreasingSubsequence(vector<int> &nums) {//建立容器int * m = new int [nums.size()];int ret = 0 ;//初始化数据m[0] = 1;//执行递推关系for(int i = 1 ; i < nums.size();i++){m[i] = 1;for(int j = 0 ; j < i ; j++){if(nums.at(i) > nums.at(j)){if(m[i] < m[j] + 1 )m[i] = m[j] + 1;           }    }if(ret < m[i]){ret = m[i];}} return ret ;}
};/******************************************************************************/
例题8:最小调整代价 lintcode:91题
给一个整数数组,调整每个数的大小,使得相邻的两个数的差不大于一个给定的整数target,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少。(整数的大小不超过100.)
对于数组[1, 4, 2, 3]和target=1,最小的调整方案是调整为[2, 3, 2, 3],调整代价之和是2。返回2。思路:这个题目我认为是非常的难的,我想了很久都没想到。存放数据的容器就很难想象的到,定义一个m[i][100]的容器。
这个题目我是看了答案的,容器定义成为m[A.size()][100],A.size()表示序列的长度,m[i][j]表示为第i个元素如果调整成j,需要花费的最小代价。(i之前的数据都是有意义,而且是最小的调整代价)
所以有m[i][j] = min{ m[i-1][j+k] //其中k的值表示为-target,+target之间的所有数据}

代码如下:
class Solution {
public:int MinAdjustmentCost(vector<int> &A, int target) {if(A.size() == 1 || A.size() == 0){return 0;}//建立存放的容器int ** m = new int* [A.size()];for(int i = 0 ; i < A.size() ; i++){m[i] = new int[100]; }//初始化数据for(int i = 0 ; i < 100 ;i ++){m[0][i] = abs(i-A.at(0));    } //循环获取数据int min;int min_j; for(int i = 1 ; i < A.size() ;i++){min_j = 100000;for(int j = 0 ; j < 100 ; j++){min = 100000;//并不是全部位置可能只有一部分。 for(int z = -target ; z < target+1 ; z++){//如果相差的数据,在target之内,不需要修改数据if(z+j < 0 || z+j >= 100){continue;}if(min > m[i-1][z+j] + abs(j-A.at(i))){min = m[i-1][z+j] + abs(j-A.at(i));      }}m[i][j] = min;if(m[i][j] < min_j){min_j = m[i][j];    }} } return min_j;}
};/******************************************************************************/
例题9:背包问题 lintcode:92题
在n个物品中挑选若干物品装入背包,最多能装多满?
假设背包的大小为m,每个物品的大小为A[i]如果有4个物品[2, 3, 5, 7]
如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。
如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。
函数需要返回最多能装满的空间大小。思路:第一次做背包问题的题目,很不知所措。借助以往的经验,他并没有设置成为m[i][j]的条件。思考了一个小时之后,我看了答案。设计一个一维数组来存放数据,bool m[x],表示的含义是x如果背包大小是x,是否可以完全放满。
m[x] = m[x] || m[x-a[k]]   //其中k表示物品的个数。为了防止重复包含,可以从后向前循环。

代码如下:
class Solution {
public:int backPack(int x, vector<int> &A) {bool v[x+1];//初始化数据v[0] = true;for(int i = 1; i < x+1 ; i++){v[i] = false;    } //循环for(int i = 0 ; i < A.size() ; i++){for(int j = x ; j >= A.at(i);j--){v[j] = v[j] || v[j-A.at(i)];}} for(int i = x ; i > 0 ;i--){if(v[i]){return i; }    } }
};后续还会继续做动态规划的题目....

转载于:https://www.cnblogs.com/qiny1012/p/9684675.html

动态规划练习合集(c++)相关推荐

  1. 一般动态规划问题合集(Leetcode题解-Python语言)

    118. 杨辉三角 class Solution:def generate(self, numRows: int) -> List[List[int]]:dp = [[0] * i for i ...

  2. 年度盘点!必看AI顶会论文、Github高星项目大合集(附链接)

    目前,国外计算机界评价学术水平主要是看在顶级学术会议上发表的论文,特别是在机器学习.计算机视觉和人工智能领域,顶级会议才是王道.本期我们盘点了2019年人工智能领域的顶会,如最核心的顶会AAAI.IJ ...

  3. 独家 | 年度盘点!必看AI顶会论文、Github高星项目大合集(附链接)

    目前,国外计算机界评价学术水平主要是看在顶级学术会议上发表的论文,特别是在机器学习.计算机视觉和人工智能领域,顶级会议才是王道.本期我们盘点了2019年人工智能领域的顶会,如最核心的顶会AAAI.IJ ...

  4. 京东java笔试_2017阿里,百度,京东java面试+笔试大合集,2018的你会吗?

    2017阿里,百度,京东java面试+笔试大合集 1.阿里 面试(一二面合集) 1.介绍一下你自己. 2.介绍一下你认为做的最好的一个项目. 3.请用五分钟的时间把你做的项目的流程图画一下. 4.项目 ...

  5. 算法基础课【合集1】

    文章目录 基础算法 785. 快速排序 786. 第k个数 787. 归并排序 788. 逆序对的数量 789. 数的范围 790. 数的三次方根 791. 高精度加法 792. 高精度减法 793. ...

  6. Java面试核心知识点(283页)Java面试题合集最新版(485页)

    阿里.腾讯两大互联网企业传来裁员消息,很多人都陷入担心,不安情绪蔓延-- 其实大家应该更冷静和理性地看待大厂裁员.每年三四月都是大厂人员调整期,这个季节是各个公司战略调整.战略规划的一个关键期,肯定会 ...

  7. 闭关30天,献上【Java一线大厂高岗面试题解析合集】,冲刺金九银十!

    概述 时间不等人,2022年转眼就要过去大半了,春招在疫情中度过,不知有多少人还在惋惜... 马上又是秋招的高峰"金九银十",估计现在就已经有不少的程序猿(媛)朋友早就踏上提前批之 ...

  8. 计算机经典书籍电子书合集

    2楼JAVA篇 此篇收录:.<Java 2核心技术>.2.<Java编程语言>.3.<Effective Java>.4.<Java解惑>.5.< ...

  9. 闭关28天,奉上[Java一线大厂高岗面试题解析合集],备战金九银十

    前言 时间不等人,2022年转眼就要过去大半了,春招在疫情中度过,不知有多少人还在惋惜... 马上又是秋招的高峰"金九银十",估计现在就已经有不少的程序猿(媛)朋友早就踏上提前批之 ...

  10. 万字长文,冲刺备战金九银十,奉上[Java一线大厂高岗面试题解析合集]

    时间不等人,2022年转眼就要过去大半了,春招在疫情中度过,不知有多少人还在惋惜... 马上又是秋招的高峰"金九银十",估计现在就已经有不少的程序猿(媛)朋友早就踏上提前批之路了吧 ...

最新文章

  1. 为什么要Zipkin
  2. python if elif else_python:通讯录(字典+while+if/else)
  3. Qt 解决 #error This file requires compiler and library support for the ISO C++ 2011 standard
  4. 赋能尖端科技 推进智能布局 |《HPC高性能计算数据存储解决方案蓝皮书》正式发布
  5. app底部导航栏的设计模板素材
  6. eclipse+maven远程(自动)部署web项目到tomcat
  7. 008 - vue node rem
  8. js 添加事件 attachEvent 和addEventListener 的用法
  9. DT大数据 scala for查询
  10. 会赚钱的教师才是好教师
  11. 2010年全国职称计算机考试专用教程——AutoCAD 2004制图软件 (含光盘下载)
  12. 面试官问如何优化慢 SQL ?(附两万字SQL面试题)
  13. C#编程之SqlHelper
  14. 人工智能培训:是学不好,还是教不好?3岁半的 BitTiger关闭
  15. CVPR 2021 | 基于模型的图像风格迁移
  16. startup_stm32xxxx.s文件问题
  17. 【Android自动化测试】Robot Framework+adb框架(三)——L3公共层
  18. 使用echarts生成海友网企业全国分布地图
  19. 笔记本模拟android,适用于PC的顶级7个免费Android模拟器在计算机PC笔记本电脑上运行Android应用...
  20. win7虚拟计算机名,电脑高手必会技能:VMware虚拟机安装win7教程

热门文章

  1. 拓端tecdat|python主题建模可视化LDA和T-SNE交互式可视化
  2. 将csv文件存入mysql数据库_将csv文件导入到mysql数据库
  3. 用文本方式将数据装入一个数据库表 mysql_文本应该放哪_MySQL用文本方式将数据装入数据库表中...
  4. python数字图像处理(6):图像的批量处理
  5. opencv实现图像目标对象区域挖掘
  6. Python命令行程序项目自动化GUI显示操作神器Gooey实践
  7. python实现基于北大开源的分词工具 pkuseg 进行分词实践
  8. python求解按等级分配糖果问题
  9. keyup常用事件_KeyUp 事件
  10. 如何获取Class类对象?