ACM学习历程—广东工业大学2016校赛决赛-网络赛C wintermelon的魔界寻路之旅(最短路 && 递推)

题目链接:http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=2

题目由于要找对称的路径,那么狠明显可以把右下角的每一块加到左上角对应的每一块上。然后就变成从左上角走到对角线的最短路径的个数。

先跑一遍最短路径得到p(i, j)从起点到(i, j)的最短路径。

然后就是找最短路径的个数。显然cnt(i, j)是它周围点能通过最短路径到它的cnt的和。这一处可以使用记忆化搜索来完成。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long
#define MOD 1000000009

using namespace std;

const int maxN = 105;
int xx[] = {-1,  1,  0,  0};
int yy[] = { 0,  0, -1,  1};
int n, a[maxN][maxN], mi;
int p[maxN][maxN];
int cnt[maxN][maxN];
bool vis[maxN*maxN];

void input()
{
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            scanf("%d", &a[i][j]);
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            if (i+j != n-1)
                a[i][j] += a[n-1-j][n-1-i];
    memset(p, -1, sizeof(p));
    memset(vis, false, sizeof(vis));
}

void cal()
{
    int k, x, y, ix, iy;
    queue<int> q;
    p[0][0] = a[0][0];
    q.push(0);
    vis[0] = true;
    while (!q.empty())
    {
        k = q.front();
        q.pop();
        vis[k] = false;
        x = k/100;
        y = k%100;
        for (int i = 0; i < 4; ++i)
        {
            ix = x+xx[i];
            iy = y+yy[i];
            if (ix+iy > n-1 || ix < 0 || iy < 0) continue;
            if (p[ix][iy] == -1 || p[ix][iy] > p[x][y]+a[ix][iy])
            {
                p[ix][iy] = p[x][y]+a[ix][iy];
                if (!vis[100*ix+iy])
                {
                    q.push(100*ix+iy);
                    vis[100*ix+iy] = true;
                }
            }
        }
    }
    mi = p[0][n-1];
    for (int i = 0; i < n; ++i)
        mi = min(mi, p[i][n-1-i]);
}

int dfs(int x, int y)
{
    if (cnt[x][y] != -1) return cnt[x][y];
    int ix, iy, all = 0;
    for (int i = 0; i < 4; ++i)
    {
        ix = x+xx[i];
        iy = y+yy[i];
        if (ix+iy > n-1 || ix < 0 || iy < 0) continue;
        if (p[ix][iy]+a[x][y] == p[x][y])
            all = (all+dfs(ix, iy))%MOD;
    }
    cnt[x][y] = all;
    return all;
}

void work()
{
    cal();
    memset(cnt, -1, sizeof(cnt));
    cnt[0][0] = 1;
    int ans = 0;
    for (int i = 0; i < n; ++i)
        if (mi == p[i][n-1-i])
            ans = (ans+dfs(i, n-1-i))%MOD;
    printf("%d\n", ans);
}

int main()
{
    //freopen("test.in", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int times = 1; times <= T; ++times)
    {
        input();
        work();
    }
    return 0;
}

时间: 2024-10-21 21:24:45

ACM学习历程—广东工业大学2016校赛决赛-网络赛C wintermelon的魔界寻路之旅(最短路 && 递推)的相关文章

ACM学习历程—广东工业大学2016校赛决赛-网络赛F 我是好人4(数论)

题目链接:http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=5 这个题目一看就是一道数论题,应该考虑使用容斥原理,这里对lcm进行容斥. 不过直接上去是T,考虑到序列中同时存在i和ki的话,其实只需要考虑i,所以先对序列中为倍数的对进行处理. 这里的容斥用了hqw的写法. 代码: #include <iostream> #include <cstdio> #include <cstdlib> #includ

ACM学习历程—广东工业大学2016校赛决赛-网络赛E 积木积水(最值问题 || 动态规划)

题目链接:http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=4 这个题目自然会考虑到去讨论最长或者最短的板子. 笔上大概模拟一下的话,就会知道,假设最长的板子是r,0和n+1位置上都是高度为0的板子,那么对于[0, r-1]中的最长板子rr,rr到r这一短应该都是被深度为a[rr]的水覆盖.同样的[0, rr-1]中的最长板子rrr,rrr到rr这一段应该是被a[rrr]覆盖,以此类推可以搞定r的前面一段,同理搞定后一段. 关于最值这一块,

ACM学习历程—广东工业大学2016校赛决赛-网络赛D 二叉树的中序遍历(数据结构)

题目链接:http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=3 这算是一个胡搞类型的题目.当然肯定是有其数据结构支撑的. 唯一的限制就是不能出现连续的两个’#’. 因为如果我从左到右构造这棵树,那么假设我构造到第i个, 如果i+1是数字,那么把前i个构成的子树作为i+1的左儿子即可. 如果i+1是’#’,那么把’#’当成i的右儿子即可. 所以只要没有两个连续的’#’,自然能通过上面的方法构造. 但是如果出现两个连续的’#’,自然前一个’#’

GG的匹配串 ______(广东工业大学2015校赛初赛)

Description 2015年广东工业大学ACM校赛要来~\(≧▽≦)/~辣辣辣,作为校赛的出题人之一,GG想出了一道水题来考考大家.相信小伙伴们都学过字符串匹配,于是字符串匹配的水题就诞生辣!GG给出了一段长度为N的大写字母序列,现在他要你修改这一段字母序列,使得这段字母序列上最前面的K个字母组成的序列与最后面的K个字母组成的序列一一匹配. 例如对于序列"ATUUUUAC"和K = 2,可以通过将第二个字母修改为"C",使得最前面的两个字母与最后面的两个字母都

广州工业大学2016校赛 F 我是好人4 dfs+容斥

Problem F: 我是好人4 Description 众所周知,我是好人!所以不会出太难的题,题意很简单 给你n个数,问你1000000000(含1e9)以内有多少个正整数不是这n个数任意一个的倍数 最后友情提供解题代码(我真是太好人了) void solve(int p[], int n) { int ans = 0; for (int i = 1; i <= 1e9; i++) { int fl = 0; for (int j = 0; j < n; j++) { if (i % p[

ACM学习历程——ZOJ 3829 Known Notation (2014牡丹江区域赛K题)(策略,栈)

Description Do you know reverse Polish notation (RPN)? It is a known notation in the area of mathematics and computer science. It is also known as postfix notation since every operator in an expression follows all of its operands. Bob is a student in

ACM学习历程—Hihocoder 1233 Boxes(bfs)(2015北京网赛)

hihoCoder挑战赛12 时间限制:1000ms 单点时限:1000ms 内存限制:256MB   描述 There is a strange storehouse in PKU. In this storehouse there are n slots for boxes, forming a line. In each slot you can pile up any amount of boxes. The limitation is that you can only pile a

ACM学习历程—HDU 4726 Kia&#39;s Calculation( 贪心&amp;&amp;计数排序)

DescriptionDoctor Ghee is teaching Kia how to calculate the sum of two integers. But Kia is so careless and alway forget to carry a number when the sum of two digits exceeds 9. For example, when she calculates 4567+5789, she will get 9246, and for 12

ACM学习历程—HDU 5023 A Corrupt Mayor&#39;s Performance Art(广州赛区网赛)(线段树)

Problem Description Corrupt governors always find ways to get dirty money. Paint something, then sell the worthless painting at a high price to someone who wants to bribe him/her on an auction, this seemed a safe way for mayor X to make money. Becaus