首页 > 其他分享 >UVA 12177 First Knight

UVA 12177 First Knight

时间:2023-05-02 19:33:06浏览次数:46  
标签:const nm int Knight 高斯消 UVA id dp First

(提醒:原题面是 \(m\) 行 \(n\) 列,这里改成了 \(n\) 行 \(m\) 列)

首先很好想到设 \(dp_{u,v}\) 为 \((u, v)\) 的期望步数
\(dp_{u, v} = \begin{cases}\sum_{i=1}^4 dp_{u + du_i,v + dv_i}\times p_i& (u \not = n \operatorname{or} v \not = m)\\ 0& (u = n \operatorname{and} v = m)\end{cases}\)
很明显有环跑个高斯消元,\(dp_{1,1}\) 即为答案的值

然后是不是以为就过了,嘻嘻,\(1\le n, m\le 40\),\(O((nm)^3)\) 直接 T 飞
发现对于“从上至下,从左至右”这种标记法,对 \(id_{x, y}\) 来说与其相邻的 \(4\) 个点分别为 \(id_{x, y} - m, id_{x, y} - 1, id_{x, y} + 1, id_{x, y} + m\),相差最大也只有 \(m\)
那就很好办了,消元的时候对于每个点,只往下找 \(m\) 行,也只往右找 \(m\) 列,因为只有这部分才能消,特别处理以下方程组的和即可,时间复杂度 \(O(nm^3)\)

然后是不是以为就过了,嘻嘻,这题卡精度,而且是往低了卡,而且卡的很恶心
如果完全没问题还是 WA 了建议照着代码重写高斯消元的写法,写的时候可能会觉得这个高斯消元的精度低得离谱,但只有这样能过(悲

#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-10;
const int N = 40 + 5, K = 4;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
int id[N][N];
double g[N * N][N * N];
int n, m;
void solve() {
    int nm = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            id[i][j] = ++nm;
        }
    }
    for (int i = 1; i <= nm; i++) {
        for (int j = 1; j <= nm + 1; j++) {
            g[i][j] = 0.0;
        }
    }
    for (int i = 1; i <= nm; i++) {
        g[i][i] = g[i][nm + 1] = 1.0;
    }
    for (int h = 0; h < 4; h++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                double p;
                scanf("%lf", &p);
                int vi = i + dx[h], vj = j + dy[h];
                if (vi < 1 || vj < 1 || vi > n || vj > m) {
                    continue;
                }
                g[id[i][j]][id[vi][vj]] = -p;
            }
        }
    }
    g[id[n][m]][id[n - 1][m]] = g[id[n][m]][id[n][m - 1]] = g[id[n][m]][nm + 1] = 0.0;
    for (int i = 1; i <= nm; i++) {
        /*
        int h = i;
        for (int j = i + 1; j <= min(i + m, nm); j++) {
            if (fabs(g[j][i]) > fabs(g[h][i])) {
                h = j;
                break;
            }
        }
        swap(g[i], g[h]);
        */
        for (int j = i; j <= min(i + m, nm); j++) {
            if (fabs(g[j][i]) > 0) {
                swap(g[i], g[j]);
                break;
            }
        }
        g[i][nm + 1] /= g[i][i];
        for (int j = min(i + m, nm); j >= i; j--) {
            g[i][j] /= g[i][i];
        }
        for (int j = i + 1; j <= min(i + m, nm); j++) {
            g[j][nm + 1] -= g[j][i] * g[i][nm + 1];
            for (int k = min(i + m, nm); k >= i; k--) {
                g[j][k] -= g[j][i] * g[i][k];
            }
        }
    }
    for (int i = nm; i >= 1; i--) {
        for (int j = i + 1; j <= min(i + m, nm); j++) {
            g[i][nm + 1] -= g[i][j] * g[j][nm + 1];
        }
    }
    printf("%.6lf\n", g[1][nm + 1]);
    return ;
}
int main() {
    for (; ~ scanf("%d%d", &n, &m) && n && m; ) {
        solve();
    }
    return 0;
}

标签:const,nm,int,Knight,高斯消,UVA,id,dp,First
From: https://www.cnblogs.com/lhzawa/p/17368099.html

相关文章

  • MFC-CListCtrl-GetFirstSelectedItemPosition获取第一个选定项的位置
     POSITIONpos=mylist4.GetFirstSelectedItemPosition();//获取第一个选定项的位置/*返回值:成功返回行号;NULL,如果项未被选定*/str.Format(_T("pos=%d\r\n"),pos);OutputDebugString(str);   ......
  • Gangsters UVA - 672
     一家饭店,有一扇大小会变得门,变化范围为[0,k]。每过一单位时间你可以让门的大小+1,-1,或者不变。客人会在不同的时间来吃饭,但是如果门的大小和他们希望的值不一样,他们就不会进来并且直接消失。吃饭要花钱,现在问饭店最多能赚多少钱。  F[i][j]=max(F[i-1][j]+v,F[i-1][j-1......
  • Marbles UVA - 10090
    给定两种购买物品的方案:花费c1元购买n1个物品,或者花费c2c2​元购买n2n2​个物品。方案可以无限使用,询问购买n个物品至少要多少元,若无法恰好购买到n个物品输出failed     #include<iostream>#include<algorithm>#include<cstring>#include<cmath>......
  • oracle 分析函数 FIRST_VALUE、LAST_VALUE
    用SCOTT/TIGER登录。FIRST_VALUE、LAST_VALUE是两个分析函数。返回结果集中排在第一位和最后一位的值。使用FIRST_VALUE:SELECTDEPTNO,JOB,SUM(SAL),FIRST_VALUE(SUM(SAL))OVER(PARTITIONBYDEPTNOORDERBYSUM(SAL))FROMEMPGROUPBYDEPTNO,JOBORDERBYDEPTNO,JOB;......
  • Hyper-drive UVA - 10542
    题意:给定一些个d维的方块,给定两点,求穿过多少方块 转化为(0,0)到(a,b)先考虑二维的 然后容斥原理#include<iostream>#include<algorithm>#include<cstring>#include<cmath>usingnamespacestd;constintN=103;#defineintlonglonginta[N],b[N],n;int......
  • Winform使用EFCore的CodeFirst(注入方式)
    1、新建项目使用vs创建一个winform的项目,这里就不演示了。2、拉取nuget包获取配置:Microsoft.Extensions.Configuration.Json注入:Microsoft.Extensions.DependencyInjectionmysqlEF:MySql.EntityFrameworkCore3、创建appsettings.json配置文件在项目......
  • Period UVA - 1371
     题意:给两个串A,B。现在把B串分为若干个部分,对每一个部分进行操作将其变为一个A串,代价为每部分操作次数的最大值求最小代价 #include<iostream>#include<algorithm>#include<cstring>usingnamespacestd;constintN=5003,M=N;#defineintlonglongconstinti......
  • Moving to Nuremberg UVA12223
    题目大意:给出n,一个无根的树,每条边上都有权值。现在每个位置都有一个景点,一个人想在一年之内去cnt[i]次景点,所以接下来给出m,表示说在m个位置上有这个人想去的地方,给出位置以及想去的次数(注意,每去一个景点都要返回自己的住处),namo这个人该住在哪里走的路程才最短。换根dp#incl......
  • Fast Food UVA - 662
    政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往。已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0<i<m。为了提高山区的文化素质,政府又决定从m个村中选择n个村建小学(设0<n≤m<500)。请根据给定的m、n以及所有......
  • Movie collection UVA - 1513
    有n个影碟,标号为1~n,位置为0~n-1,每次取出一个影碟看完后,将其放在最前面(标号为0处),问每个影碟取出前,其位置之前有多少个影碟 开2倍数组,"i放置前面"这个操作add(i,-1),add(newi,1)  #include<iostream>#include<cstring>#include<algorithm>#include<vector>usingn......