机器学习中常用的距离度量汇总

距离的定义 在机器学习中,我们通过计算不同样本在特征空间中的距离来评估样本间的相似度,进而为其进行分类。根据样本特征空间的不同,我们需要选择合适的距离度量方法。一般而言,对于距离度量函数$d(x,y)$,其需要满足如下性质: 非负性:$d(x,y)\geq 0$ 同一性:$d(x,y)=0\Leftrightarrow x=y$ 对称性:$d(x,y)=d(y,x)$ 三角不等式:$d(x,y)\leq d(x,z)+d(z,y)$ 根据样本特征空间的不同,我们把度量的距离分为:空间距离、字符距离、集合距离、分布距离。 空间距离 欧几里得距离(Euc...

2023年8月18日 · 16 分钟 · 7795 字 · Kai Wang

SGU 144 - Meeting

Description Two of the three members of the winning team of one of the ACM regional contests are going to meet in order to train for the upcoming World Finals. They decided that they will meet sometime between $X$ o’clock and $Y$ o’clock. Because they never get anywhere on time (they were late even on the day of the regional contest), they did not set an exact time when they will meet. However, they decided that the one who gets first at the meeting point will not wait more than $Z$ minutes for the other one (they calculated that, if the other one will not come within $Z$ minutes from the arrival of the first of them, then it is very probable that he will not show up at all). Knowing that, in the end, both of them will show up at some time between $X$ o’clock and $Y$ o’clock (not necessarily after an integer number of minutes), compute which is the probability that they will actually meet. Input The input will contain 2 integer numbers $X$ and $Y$ ($0\leq X < Y\leq 24$) and one real number $Z$ ($0 < Z\leq 60(Y-X)$). Output You should output the required probability with 7 decimal digits (rounded according to the 8th decimal digit). Sample Input 11 12 20.0 Sample Output 0.5555556 Analysis 这是一道纯粹的数学概率题,我们可以进行公式推导。首先我们需要...

2015年7月22日 · 1 分钟 · 464 字 · Kai Wang

SGU 116 - Index of super-prime

Description Let $P_1, P_2,\cdots ,P_N,\cdots$ be a sequence of prime numbers. Super-prime number is such a prime number that its current number in prime numbers sequence is a prime number too. For example, 3 is a super-prime number, but 7 is not. Index of super-prime for number is 0 iff it is impossible to present it as a sum of few (maybe one) super-prime numbers, and if such presentation exists, index is equal to minimal number of items in such presentation. Your task is to find index of super-prime for given numbers and find optimal presentation as a sum of super-primes. Input There is a positive integer number in input. Number is not more than 10000. Output Write index $I$ for given number as the first number in line. Write I super-primes numbers that are items in optimal presentation for given number. Write these I numbers in order of non-increasing. Sample Input 6 Sample Output 2 3 3 Analysis 首先,我们可以根据筛法求出 10000 以内的素数,接下来我们继续利用筛法,求出这些素数中,下标为素数的超级素数,这样我们就得到了题目中所需要的超级素数。 对于寻找一个最优的组合,我们可以使用 0/1 背...

2015年7月20日 · 2 分钟 · 519 字 · Kai Wang

专题一、简单搜索 - Virtual Judge

很久以前刷完了 Virtual Judge 上的简单搜索专题,现总结如下: POJ 1321 由于题目的数据范围比较小,可以直接 dfs 暴力。读入时记录每个空位的位置,保存在 pX[] 以及 pY[] 数组中。暴力的时候统计当前处理第几个空格以及当前处理到了第几行即可。 #include <iostream> #include <memory.h> using namespace std; const int MAX = 128; long long ans; int N, K, nCnt; bool pUsed[MAX]; int pX[MAX], pY[MAX]; int pRow[MAX], pCol[MAX]; void dfs(int x, int y); int main() { char dwTmp; while(cin >> N >> K) { if(N == -1 && K == -1) { break; } nCnt = 0; ans = 0; for(int i = 1; i <= N; i++) { for(int j = 1; j <= N; j++) { cin >> dwTmp; if(dwTmp == '#') { nCnt++; pX[nCnt] = i; pY[nCnt] = j; } } cin.ignore(); } memset(pRow, 0, sizeof(pRow)); memset(pCol, 0, sizeof(pCol)); memset(pUsed, false, sizeof(pUsed)); dfs(1, 0); cout << ans << endl; } return 0; } void dfs(int x, int y) { if(y == K) { ans++; } else { for(int i = x; i <= nCnt; i++) { if(!(pUsed[i] || pRow[pX[i]] || pCol[pY[i]])) { pRow[pX[i]]++; pCol[pY[i]]++; pUsed[i] = true;...

2015年6月8日 · 9 分钟 · 4250 字 · Kai Wang

2048 游戏制作过程(Java 描述):第五节、界面美化

这一节,我们将介绍游戏界面的美化以及游戏数据的存储。 首先创建一个 color.xml 资源文件,用来保存每个数字对应的背景色和前景色。右击 res 文件夹,选择 New,单击 Android resource file,输入 color,单击 Next 即可。 新建资源 修改代码如下: <?xml version="1.0" encoding="utf-8"?> <resources> <color name="bg2">#eee4da</color> <color name="text2">#776e65</color> <color name="bg4">#ede0c8</color> <color name="text4">#776e65</color> <color name="bg8">#f2b179</color> <color name="text8">#f9f6f2</color> <color name="bg16">#f59563</color> <color name="text16">#f9f6f2</color> <color name="bg32">#f67c5f</color> <color name="text32">#f9f6f2</color> <color name="bg64">#f65e3b</color> <color name="text64">#f9f6f2</color> <color name="bg128">#edcf72</color> <color name="text128">#f9f6f2</color> <color name="bg256">#edcc61</color> <color name="text256">#f9f6f2</color> <color name="bg512">#edc850</color> <color name="text512">#f9f6f2</color> <color name="bg1024">#edc53f</color> <color name="text1024">#f9f6f2</color> <color name="bg2048">#edc22e</color> <color name="text2048">#f9f6f2</color> <color name="bgsuper">#3c3a32</color> <color name="textsuper">#f9f6f2</color> </resources> 其中 bg 表示背景色,text 表示前景色,切换到 Card 界面,在 setNumber 中添加如下代码: switch(number) { case 0: tvNumber.setBackgroundColor(0x33FFFFFF); break; case 2: tvNumber.setTextColor(getResources().getColor(R.color.text2)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg2)); break; case 4: tvNumber.setTextColor(getResources().getColor(R.color.text4)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg4)); break; case 8: tvNumber.setTextColor(getResources().getColor(R.color.text8)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg8)); break; case 16: tvNumber.setTextColor(getResources().getColor(R.color.text16)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg16)); break; case 32: tvNumber.setTextColor(getResources().getColor(R.color.text32)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg32)); break; case 64: tvNumber.setTextColor(getResources().getColor(R.color.text64)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg64)); break; case 128: tvNumber.setTextColor(getResources().getColor(R.color.text128)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg128)); break; case 256: tvNumber.setTextColor(getResources().getColor(R.color.text256)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg256)); break; case 512: tvNumber.setTextColor(getResources().getColor(R.color.text512)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg512)); break; case 1024: tvNumber.setTextColor(getResources().getColor(R.color.text1024)); tvNumber.setBackgroundColor(getResources().getColor(R.color.bg1024)); break; case...

2015年5月17日 · 3 分钟 · 1347 字 · Kai Wang

2048 游戏制作过程(Java 描述):第四节、游戏逻辑

上一节中,我们已经成功的将卡牌添加到了游戏中,但只是显示在了界面上,并没有保存下来。我们在 GameView 中定义一个二维数组用来保存游戏界面的卡牌。 private Card[][] cardMap = new Card[4][4]; // 记录游戏 接下来,我们需要将初始化时候添加的卡片添加到 cardMap 数组中,如下图所示: private void addCards(int cardSize) { Card card; for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { card = new Card(getContext()); card.setNumber(2); addView(card, cardSzie, cardSize); cardMap[i][j] = card; // 添加卡片 } } } 这样一来,我们就将游戏界面记录下来了。 但是上一节中,我们一下子就生成了 16 张卡片,这和平时游戏的时候不一致。而且我们只能生成卡片 2。为了改进它,我们可以定义一个函数 addRandomNumbe...

2015年5月15日 · 7 分钟 · 3052 字 · Kai Wang

2048 游戏制作过程(Java 描述):第三节、创建界面

首先,我们要使得我们的程序能够判断用户的手势,一共为上、下、左、右四种。在 GameView 类中添加如下代码: private void initGameView() { setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return false; } }); } 接下来,我们来分析一下如何进行手势判断。首先,用户的手势输入应该有两个数据,一个是按下的屏幕位置,一个是放开的屏幕位置。那么我们只需要计算横向和竖向坐标差的绝对值,绝对值较大的一个方向则是用户需求的方向。至于横向中的左右和竖向中的上下,我们可以通过按下和放开的位置的大小进行比较得出。 有了上面的分析,我们开始写代码: private void initGameView() { setOnTouchListener(new View.OnTouchListener() { private float startX, startY; // 起始位置 private float endX, endY; // 终了位置...

2015年5月14日 · 4 分钟 · 1539 字 · Kai Wang

2048 游戏制作过程(Java 描述):第二节、基本设置

首先,我们需要修改一下应用的图标。准备一个 png 格式的图标文件。如下图所示: App 图标 接下来,找到上一节中保存项目的位置,依次展开文件夹中的 2048/Game2048/app/src/main/res 目录,如下图所示: App 图标 分别将刚才制作完成的图标文件更改名字为 ic_launcher.png,并且修改尺寸为 144×144、96×96、72×72、48×48,分别放入 drawable-xxhdip、drawable-xhdpi、drawable-hdpi、drawble-mdpi 文件夹覆盖其中的图标文件。需要用到这么多尺寸的图片,是由于 Android 应用程序需要兼容不同的客...

2015年5月14日 · 3 分钟 · 1115 字 · Kai Wang

2048 游戏制作过程(Java 描述):第一节、创建项目

自从关于扫雷游戏制作过程的文章发布后,有同学让我写一些关于移动开发的文章,并且建议以雷电这款游戏为例。然而考虑到该项目对于初学者来说代码量较大,所以暂且不涉及这部分,转而使用较为简单的 2048 游戏作为例子,可能对于初学者来说更容易上手,并且也更容易自己动手实现出来。 本项目已根据文章进度托管在 GitHub 上:2048,读者可以自行查看。 由于没有 Mac,因此只能介绍关于 Android 平台相关的开发知识。然而进行 Android 开发之前,需要搭建 Android 开发环境,这一步比较有难度的,主要是各个软件的配置较为麻烦,使得很多初学者望而却步。目前主流的 IDE...

2015年5月8日 · 4 分钟 · 1566 字 · Kai Wang

扫雷游戏制作过程(CSharp 描述):第八节、整体完善

这一节我们将介绍结束游戏的方法,以及一些整体方面的完善。首先考虑失败的情况,它会将所有的地雷都显示出来。我们新建一个 GameLost 函数: private void GameLost() { for(int i = 1; i<= nWidth; i++) { for(int j = 1; j<= nHeight; j++) { if(pMine[i, j] == -1 && (pState[i, j] == 0 || pState[i, j] == 3)) // 未点开或者标记为问号的雷 { pState[i, j] = 1; // 点开该地雷 } } } } 在游戏结束的地方调用 GameLost 函数,因为我们上一节中讲述的游戏结束都是失败的情况: if(nFlagCnt == nSysCnt || nFlagCnt + nDoubtCnt == nSysCnt) // 打开九宫格 { bool bFlag = OpenMine(MouseFocus.X, MouseFocus.Y); if(!bFlag) // 周围有地雷 { // 结束游戏 GameLost(); } } if(pMine[MouseFocus.X, MouseFocus.Y] != -1 && pState[MouseFocus.X, MouseFocus.Y] == 0) { dfs(MouseFocus.X, MouseFocus.Y); } else { // 地雷,游戏结束 GameLost(); } 我们发现游戏结束的时候,虽然所有的格子都打开了,但是并...

2015年5月2日 · 5 分钟 · 2300 字 · Kai Wang