POJ 3756 Chess Game [期望+高斯消元]

  这个模型跟小时候玩的大富翁棋类游戏差不多,起点是0,终点是N,每次掷骰子走1~6步,格子分为3种,前进1~6格,后退1~6格,以及停止一回合,求到达终点所需回合数的期望。

  用E(I)表示从第I个格子走到终点所需回合的期望,E(N)=0,转移方程为 E(I)=sum(1/6*(E(K1)+1))+sum(1/6*(E(K2)+2))。K1,K2都是从I掷1~6能走到的格子,如果这个格子有操作,就要跳到操作后的格子,第一个sum里求的是不会停一回合的期望和,第二个sum里求的是走到停一回合格子的期望和。

  因为有后退操作,所以转移是有环的,不能用记忆化搜索,要用高斯消元来做。

  一开始可以DFS一遍标记所以能到达的格子,这样可以直接判断是否有解。对于不可达的点,也不需要去消元。

  比较蛋疼的是遇到端点折回的情况,比如在N=2时,在1掷了个5,那路线就是1->2->1->0->1->2。。没总结出用什么式子算,索性写了个暴力模拟一直调整直到到达0~N的范围中。。

  这题精度比较低,暴力的循环DP1000次貌似也能过。。我本机随机数据测了一下,暴力DP的精度还是有限的,2位的精度基本都对上了,但位数再高一点精度就差不少了,所以这类题最好还是高斯消元解吧,反正也不麻烦。

  

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <math.h>
  4 #include <algorithm>
  5 #define MAXN 105
  6 #define INF 0x3f3f3f3f
  7 #define eps 1e-9
  8 using namespace std;
  9 int n, nf, tx, ty;
 10 int reach[MAXN], fp[MAXN], id[MAXN], ids;
 11 double x[MAXN][MAXN], ans[MAXN];
 12 double gauss(int n,int m) {
 13     int row = 0, col = 0;
 14     for (;row < n && col < m; col++) {
 15         int maxr = row;
 16         for (int i = row+1; i < n; i++)
 17             if (fabs(x[i][col]) > fabs(x[maxr][col]))maxr = i;
 18         if (fabs(x[maxr][col]) < eps) continue;
 19         if (maxr != row) for (int i = 0; i <= m; i++) swap(x[row][i], x[maxr][i]);
 20         for (int k1 = row+1; k1 < n; k1++) {
 21             double div = x[k1][col] / x[row][col];
 22             for (int k2 = col; k2 <= m; k2++) {
 23                 x[k1][k2] -= div * x[row][k2];
 24             }
 25         }
 26         row++;
 27     }
 28     memset(ans, 0, sizeof ans);
 29     for (int i = n-1; i >= 0; i--) {
 30         double tmp = 0;
 31         for (int j = i+1; j < m; j++)
 32             tmp += ans[j] * x[i][j];
 33         ans[i] = (- x[i][m] - tmp) / x[i][i];
 34     }
 35     return ans[0];
 36 }
 37 int getnp(int p,int i) {
 38     int np = i+p;
 39     while (np < 0 || np > n) np = np > n ? 2*n-np : -np;
 40     return np;
 41 }
 42 void dfsreach(int p) {
 43     reach[p] = 1;
 44     for (int i = 1;i <= 6; i++) {
 45         int np = getnp(p, i);
 46         if (fp[np] != INF) np = getnp(np, fp[np]);
 47         if (!reach[np]) dfsreach(np);
 48     }
 49 }
 50 void solve() {
 51     memset(reach, 0 ,sizeof reach);
 52     dfsreach(0);
 53     if (reach[n] == 0) {
 54         printf("Impossible\n");
 55         return;
 56     }
 57     ids = 0;
 58     double one = 1.0/6.0;
 59     for (int i = 0; i < n; i++) if (reach[i]) id[i] = ids++;
 60     memset(x, 0, sizeof x);
 61     for (int p = 0; p < n; p++) {
 62         if (reach[p] == 0) continue;
 63         x[id[p]][id[p]] = -1;
 64         for (int i = 1; i <= 6; i++) {
 65             int np = getnp(p, i), nfp = fp[np];
 66             if (fp[np] != INF) np = getnp(np, fp[np]);
 67             //已经到达终点
 68             if (np == n) {
 69                 x[id[p]][ids] += one;
 70             //注意,是第一步跳到了停止上才是停止
 71             } else if(nfp == 0) {
 72                 x[id[p]][id[np]] += one;
 73                 x[id[p]][ids] += one * 2;
 74             } else {
 75                 x[id[p]][id[np]] += one;
 76                 x[id[p]][ids] += one;
 77             }
 78         }
 79     }
 80     double x = gauss(ids, ids);
 81     printf("%.2f\n", x);
 82 }
 83 int main(){
 84     freopen("test.in","r",stdin);
 85     freopen("test.out","w",stdout);
 86     while (scanf("%d", &n) != EOF) {
 87         scanf("%d", &nf);
 88         memset(fp, 0x3f, sizeof fp);
 89         for (int i = 0; i < nf; i++)
 90             scanf("%d%d", &tx, &ty), fp[tx] = ty;
 91         scanf("%d", &nf);
 92         for (int i = 0; i < nf; i++)
 93             scanf("%d%d", &tx, &ty), fp[tx] = -ty;
 94         scanf("%d", &nf);
 95         for (int i = 0; i < nf; i++)
 96             scanf("%d", &tx), fp[tx] = 0;
 97         solve();
 98     }
 99     return 0;
100 }

 

  

转载于:https://www.cnblogs.com/swm8023/archive/2012/09/21/2696690.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
系统根据B/S,即所谓的电脑浏览器/网络服务器方式,运用Java技术性,挑选MySQL作为后台系统。系统主要包含对客服聊天管理、字典表管理、公告信息管理、金融工具管理、金融工具收藏管理、金融工具银行卡管理、借款管理、理财产品管理、理财产品收藏管理、理财产品银行卡管理、理财银行卡信息管理、银行卡管理、存款管理、银行卡记录管理、取款管理、转账管理、用户管理、员工管理等功能模块。 文中重点介绍了银行管理的专业技术发展背景和发展状况,随后遵照软件传统式研发流程,最先挑选适用思维和语言软件开发平台,依据需求分析报告模块和设计据库结构,再根据系统功能模块的设计制作系统功能模块图、流程表和E-R图。随后设计架构以及编写代码,并实现系统能模块。最终基本完成系统检测和功能测试。结果显示,该系统能够实现所需要的作用,工作状态没有明显缺陷。 系统登录功能是程序必不可少的功能,在登录页面必填的据有两项,一项就是账号,另一项据就是密码,当管理员正确填写并提交这二者据之后,管理员就可以进入系统后台功能操作区。进入银行卡列表,管理员可以进行查看列表、模糊搜索以及相关维护等操作。用户进入系统可以查看公告和模糊搜索公告信息、也可以进行公告维护操作。理财产品管理页面,管理员可以进行查看列表、模糊搜索以及相关维护等操作。产品类型管理页面,此页面提供给管理员的功能有:新增产品类型,修改产品类型,删除产品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值