这是编程竞赛的问题。可以找到它的输入here和输出here。
一个喝醉了的男人想离开酒吧回到他家。但他不记得他的家在哪里。所以,他会敲开城市的每个城市,等待他的家人接待他(总是会有人等着接待他)。给定邻接矩阵 A 。每个值(i,j)表示醉酒男子离开第i个地方并到达第j个地方的概率。醉酒男子最多 m 步骤找不到他家的概率是多少?
到目前为止,我甚至不知道这是什么问题。搜索网络和书籍我发现要计算离开节点的概率 i a以 m 步骤进入节点 j 是由位置(i,j)给出 A 矩阵(A ^ m)的 m 输入的第一行由四行整数 n (0 <= n <= 100), t (0 对于每个测试用例,输出以两行给出,并且必须采用以下形式: Instancia d : 输入示例: 2 1 2 1 输出示例: Instancia 1 Instancia 2 对算法,书籍,网站或提示的任何帮助表示赞赏; 到目前为止,我必须解决这个问题的信息才能生成这个代码: 答案 0 :(得分:3) 正如stgatilov所说,你忘记了他到达那里后就不会离开家。 但不需要动态编程。只需稍微改变一下概率矩阵:如果他的家位于 然后它应该可以正常工作。 注意:还有一个可能的优化。您可以使用Exponentiation by squaring。 答案 1 :(得分:-1) 您似乎忘记了该男子可以少而不是 m 步骤回家。现在你计算在完全 m 步骤之后他不会在家中的概率,因为他没有因任何原因而停止。 我认为您最好实施一些动态编程。例如 R [i,p] =男人没有在 i 步骤中回家的概率,并且在 i -step步骤之后他会到位 p 。重新计算有点类似于矩阵乘法,答案是通过对表 R 的相应条目求和得到的。幂。而且醉酒男子不能到家的概率可以直接计算或计算1 - 醉酒男子到达他家的概率(P(A)= 1 - P(不是A))。
的 v
其中d表示实例的编号(从1开始),v是四舍五入到小数点后6位的概率。每个测试用例之间都有一个空行。
0.5 0.5
0.5 0.5
3 1 2 2
0.25 0.25 0.5
0.25 0.5 0.25
0.5 0.25 0.25
0
0.500000
0.562500 #include <stdio.h>
#include <string.h>
struct Matrix {
double v[100][100];
int row, col; // row x col
Matrix(int n, int m) {
memset(v, 0, sizeof(v));
col = n;
row = m;
}
Matrix operator*(const Matrix& x) const {
Matrix ret(row, x.col);
for(int i = 0; i < row; i++) {
for(int k = 0; k < col; k++) {
if (v[i][k])
for(int j = 0; j < x.col; j++)
ret.v[i][j] += v[i][k] * x.v[k][j];
}
}
return ret;
}
};
int main(){
int n,t,k,m;
int inst = 0;
while(scanf("%d %d %d %d",&n,&t,&k,&m) == 4){
Matrix mat(n,n);
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
scanf("%lf",&mat.v[i][j]);
//identity matrix
Matrix aux(n,n);
for (int i = 0; i < n; ++i)
aux.v[i][i] = 1;
//take the power of the matrix
for (int i = 0; i < m; ++i) {
aux = aux*mat;
/* PRINT MATRIX
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
printf("%lf ",aux.v[i][j]);
}
printf("\n");
}
*/
}
printf("Instancia %d\n%.6lf\n\n",++inst,aux.v[t-1][k-1]);
}
}
2 个答案:
i
,那么将概率从i
改为i
改为1
,对于不等于j
的任何i
,请将<{>从i
升级到j
的概率更改为0
。m
次