2017icpc沈阳站_M_HDU-6229_(思维)

2023-05-16

链接: http://acm.hdu.edu.cn/showproblem.php?pid=6229

题意: 给一个矩阵上面有一些坏点,坏点不能走,起点是 ( 0 , 0 ) (0, 0) (0,0) ,保证所有可行点联通。在每个点走向其他可走方向(上下左右)和待在原地的概率是相同的。问无限次后,在位置 { ( x , y ) ∣ x + y ≥ N − 1 } \{(x, y)|x + y ≥ N - 1 \} {(x,y)x+yN1} 的部分的概率总和是多少。

思路: 完全没思路,看完题解并没有理解,并不知道是怎么想出来…。现在开始搬运,每个点给一个权值,权值是到达当前位置的方案数,比如四个角就是 3 3 3,矩阵边沿就是 4 4 4,内部是 5 5 5。坏点是 0 0 0(不可达),并且坏点周围的点要减 1 1 1,因为坏点周围的点不能从坏点到达。 结果是 下三角的权值 / 总权值。对于此我有三种解法。

  1. 二分
    先算出没有坏点的下三角权值和、权值总和。按照先 x x x y y y 排序所有坏点。遍历所有坏点,二分找四个方向上是否有坏点,如果有,不做任何操作(因为坏点周围的那个点是坏点,没有影响);如果没有坏点,权值总和减一,如果位置在下三角,下三角权值和减一(就是坏点对周围的点的贡献是 − 1 -1 1)。最后别忘了也要减去所有坏点的权值。

  2. set
    和二分思路一样,多了一步把所有坏点插入 s e t set set ,然后查找的时候直接 c o u n t count count 找点, 1 1 1 就找到了, 0 0 0 就没有。其实好像比二分好写多了。也不会出现 k k k 写成 n n n 的智障情况。其实就是因为我二分写毒了,把 k k k 写成 n n n 了,导致一直 W A WA WA,才写的 s e t set set ,没想到一下就过了,很无奈,不过也告诉了我二分没错,才浪费了我几个小时 d e b u g debug debug 二分。

  3. map
    其实这才是最好写的。遍历所有坏点,坏点存入 m a p map map 他的值是当前点的权值。坏点周围的点的值就是 当前值 加一,然后取点的权值加一后的值的最小值。这是在算有负贡献的点的负贡献值,取最小值是因为一个点只能有权值这么多的负贡献。最后遍历 m a p map map 减去所有负贡献即可。

1. 二 分 1. 二分 1.

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 11000;

struct node {
    int x, y;
    bool operator < (const node &d) const {
        return (x == d.x)?(y < d.y):(x < d.x);
    }
};
int t, cas;
LL n, k;
std::map<int, int> m[MAXN];
node bad[MAXN];
set<node > se;
int dir[][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

bool check(int x, int y) {
    if(x < 0 || x > n-1 || y < 0 || y > n-1) return true;
    return false;
}
int where(int x, int y) {
    if((x == 0 && y == 0) || (x == 0 && y == n-1) || (x == n-1 && y == 0) || (x == n-1 && y == n-1))
        return 3;
    if(x == 0 || x == n-1 || y == 0 || y == n-1)
        return 4;
    return 5;
}

int main(int argc, char const *argv[])
{
    scanf("%d", &t);
    while(t--) {
        scanf("%lld%lld", &n, &k);
        if(n == 1) {
            printf("Case #%d: 1/1\n", ++cas);
            continue;
        }
        se.clear();
        for (int i = 0; i < k; ++i) {
            scanf("%d%d", &bad[i].x, &bad[i].y);
            // se.insert(bad[i]);
            // cout<<"bad : "<<i <<" "<<bad[i].x<<" "<<bad[i].y<<endl;
        }
        LL sum = 4*3 + 4*(n-2)*4 + (n-2)*(n-2)*5;
        LL part = 3*3 + 2*(n-2)*4 + ((n-1)*(n-2)/2)*5;
        // cout<<"sum : "<<sum<<endl;
        // cout<<"part : "<<part<<endl;
        sort(bad, bad+k);
        for (int i = 0; i < k; ++i) {
            int x = bad[i].x;
            int y = bad[i].y;
            // cout<<"x y 0: "<<bad[i].x<<" "<<bad[i].y<<endl;

            int cnt = 0, cnt2 = 0, num = 0, num2 = 0;
            for (int d = 0; d < 4; ++d) {
                if(check(x+dir[d][0], y+dir[d][1])) continue;
                node tm;
                tm.x = x+dir[d][0];
                tm.y = y+dir[d][1];
                bool flag = 0;
                /*for (int j = 0; j < k; ++j) { // 遍历竟然能过
                    if(x+dir[d][0] == bad[j].x && y+dir[d][1] == bad[j].y) {
                        flag = 1;
                        break;
                    }
                }
                if(flag) continue;*/ // 二分终于过了,没问题,是我把 长度k 写成 n 了,kao,以后还是用set保险些。
                int pos = lower_bound(bad, bad+k, tm) - bad;// 这里的 k 错了
                // if(x+dir[d][0] == 3 && y+dir[d][1] == 1) {
/*
                    cout<<"bad : "<<endl;
                    for (int tmpt = 0; tmpt < k; ++tmpt) {
                        cout<<bad[tmpt].x<<" "<<bad[tmpt].y<<endl;
                    }cout<<endl;*/

                    // cout<<"x+dir[d][0] y+dir[d][1] : "<<x+dir[d][0]<<" "<<y+dir[d][1]<<endl;
                    // cout<<"pos : "<<pos<<endl;
                    // cout<<"bad[pos] : "<<bad[pos].x<<" "<<bad[pos].y<<endl;
                // }
                // 这里的 k 也错了
                if((pos != k) && (bad[pos].x == x+dir[d][0] && bad[pos].y == y+dir[d][1])) {
                    // cout<<"x+dir[d][0] y+dir[d][1] : "<<x+dir[d][0]<<" "<<y+dir[d][1]<<endl;
                    // cout<<"pos : "<<pos<<endl;
                    // cout<<"bad[pos] : "<<bad[pos].x<<" "<<bad[pos].y<<endl;
                    continue;
                    // num++;
                    // if(x+dir[d][0] + y+dir[d][1] >= n-1) num2++;
                }
                // if(se.count(tm)) continue;// 用 set 可以,以后找有没有的问题就用set,
                sum--;
                // cnt++;
                if(x+dir[d][0] + y+dir[d][1] >= n-1) part--;
                    // cnt2++;

            }
            int tmp = where(x, y);
            // cout<<"x y : "<<x<<" "<<y<<endl;
            // cout<<"tmp : "<<tmp<<endl;
            // cout<<"cnt2 : "<<cnt2<<endl;
            // cout<<"num2 : "<<num2<<endl;
            // cout<<endl<<endl;
            if(x+y >= n-1) {
                part -= tmp;
            }

            // part -= (cnt2-num2);
                // cout<<"part : "<<part<<endl;
            sum -= tmp;
            // sum -= (cnt-num);
        }
        LL g = __gcd(part, sum);
        printf("Case #%d: %lld/%lld\n", ++cas, part/g, sum/g);
    }
    return 0;
}

看我的调试代码就知道我 d e b u g debug debug 多久了,简直崩溃。

2. s e t 2. set 2.set

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 11000;

struct node {
    int x, y;
    bool operator < (const node &d) const {
        return (x == d.x)?(y < d.y):(x < d.x);
    }
};
int t, cas;
LL n, k;
std::map<int, int> m[MAXN];
node bad[MAXN];
set<node > se;
int dir[][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

bool check(int x, int y) {
    if(x < 0 || x > n-1 || y < 0 || y > n-1) return true;
    return false;
}
int where(int x, int y) {
    if((x == 0 && y == 0) || (x == 0 && y == n-1) || (x == n-1 && y == 0) || (x == n-1 && y == n-1))
        return 3;
    if(x == 0 || x == n-1 || y == 0 || y == n-1)
        return 4;
    return 5;
}

int main(int argc, char const *argv[])
{
    scanf("%d", &t);
    while(t--) {
        scanf("%lld%lld", &n, &k);
        if(n == 1) {
            printf("Case #%d: 1/1\n", ++cas);
            continue;
        }
        se.clear();
        for (int i = 0; i < k; ++i) {
            scanf("%d%d", &bad[i].x, &bad[i].y);
            se.insert(bad[i]);
            // cout<<"bad : "<<i <<" "<<bad[i].x<<" "<<bad[i].y<<endl;
        }
        LL sum = 4*3 + 4*(n-2)*4 + (n-2)*(n-2)*5;
        LL part = 3*3 + 2*(n-2)*4 + ((n-1)*(n-2)/2)*5;
        // cout<<"sum : "<<sum<<endl;
        // cout<<"part : "<<part<<endl;
        // sort(bad, bad+k);
        for (int i = 0; i < k; ++i) {
            int x = bad[i].x;
            int y = bad[i].y;
            // cout<<"x y 0: "<<bad[i].x<<" "<<bad[i].y<<endl;

            int cnt = 0, cnt2 = 0, num = 0, num2 = 0;
            for (int d = 0; d < 4; ++d) {
                if(check(x+dir[d][0], y+dir[d][1])) continue;
                node tm;
                tm.x = x+dir[d][0];
                tm.y = y+dir[d][1];
                bool flag = 0;
                /*for (int j = 0; j < k; ++j) { // 遍历竟然能过
                    if(x+dir[d][0] == bad[j].x && y+dir[d][1] == bad[j].y) {
                        flag = 1;
                        break;
                    }
                }
                if(flag) continue;*//* // 二分失败,
                int pos = lower_bound(bad, bad+n, tm) - bad;
                if((pos != n) && (bad[pos].x == x+dir[d][0] && bad[pos].y == y+dir[d][1])) {
                    cout<<"x+dir[d][0] y+dir[d][1] : "<<x+dir[d][0]<<" "<<y+dir[d][1]<<endl;
                    cout<<"pos : "<<pos<<endl;
                    cout<<"bad[pos] : "<<bad[pos].x<<" "<<bad[pos].y<<endl;
                    continue;
                    // num++;
                    // if(x+dir[d][0] + y+dir[d][1] >= n-1) num2++;
                }*/
                if(se.count(tm)) {
                    // cout<<"-------------------------------"<<endl;
                    // cout<<"x+dir[d][0] y+dir[d][1] : "<<x+dir[d][0]<<" "<<y+dir[d][1]<<endl;
                    continue;// 用 set 可以,以后找有没有的问题就用set,
                }
                sum--;
                // cout<<"sum : "<<sum<<endl;
                // cnt++;
                if(x+dir[d][0] + y+dir[d][1] >= n-1) part--;
                    // cnt2++;

            }
            int tmp = where(x, y);
            // cout<<"x y : "<<x<<" "<<y<<endl;
            // cout<<"tmp : "<<tmp<<endl;
            // cout<<"cnt2 : "<<cnt2<<endl;
            // cout<<"num2 : "<<num2<<endl;
            // cout<<endl<<endl;
            if(x+y >= n-1) {
                part -= tmp;
            }

            // part -= (cnt2-num2);
                // cout<<"part : "<<part<<endl;
            sum -= tmp;
            // sum -= (cnt-num);
        }
        LL g = __gcd(part, sum);
        printf("Case #%d: %lld/%lld\n", ++cas, part/g, sum/g);
    }
    return 0;
}

这里是一次过的,调试代码是和二分对拍的时候写的。

3. m a p 3. map 3.map

#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long LL;
const int MAXN = 11000;

struct node {
    int x, y;
    bool operator < (const node &d) const {
        return (x == d.x)?(y < d.y):(x < d.x);
    }
};
int t, cas;
LL n, k;
std::map<node, int> mp;
node bad[MAXN];
set<node > se;
int dir[][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

bool check(int x, int y) {
    if(x < 0 || x > n-1 || y < 0 || y > n-1) return true;
    return false;
}
int where(int x, int y) {
    if((x == 0 && y == 0) || (x == 0 && y == n-1) || (x == n-1 && y == 0) || (x == n-1 && y == n-1))
        return 3;
    if(x == 0 || x == n-1 || y == 0 || y == n-1)
        return 4;
    return 5;
}

int main(int argc, char const *argv[])
{
    scanf("%d", &t);
    while(t--) {
        scanf("%lld%lld", &n, &k);
        if(n == 1) {
            printf("Case #%d: 1/1\n", ++cas);
            continue;
        }
        mp.clear();
        for (int i = 0; i < k; ++i) {
            scanf("%d%d", &bad[i].x, &bad[i].y);
        }
        LL sum = 4*3 + 4*(n-2)*4 + (n-2)*(n-2)*5;
        LL part = 3*3 + 2*(n-2)*4 + ((n-1)*(n-2)/2)*5;
        for (int i = 0; i < k; ++i) {
            int x = bad[i].x;
            int y = bad[i].y;
            mp[(node){x, y}] = where(x, y);
            for (int d = 0; d < 4; ++d) {
                if(check(x+dir[d][0], y+dir[d][1])) continue;
                node tm;
                tm.x = x+dir[d][0];
                tm.y = y+dir[d][1];
                ++mp[tm];
                mp[tm] = min(mp[tm], where(tm.x, tm.y));
            }
        }
        for (std::map<node, int>::iterator it = mp.begin(); it != mp.end(); ++it) {
            int x = (it->fi).x;
            int y = (it->fi).y;
            int tmp = it->se;
            sum -= tmp;
            if(x + y >= n-1) part -= tmp;
        }
        /*for(auto cnt : mp) {
            int x = cnt.fi.x;
            int y = cnt.fi.y;
            int tmp = cnt.se;
            sum -= tmp;
            if(x + y >= n-1) part -= tmp;
        }*/
        LL g = __gcd(part, sum);
        printf("Case #%d: %lld/%lld\n", ++cas, part/g, sum/g);
    }
    return 0;
}

m a p map map 其实是可以用auto类型遍历的,但是必须用 c + + 11 c++11 c++11 的标准编译, g + + g++ g++ 的命令是 g++ -g -Wall -std=c++11 M(map).cpp

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

2017icpc沈阳站_M_HDU-6229_(思维) 的相关文章

  • HDU 1275

    两车追及或相遇问题 Time Limit 2000 1000 MS Java Others Memory Limit 65536 32768 K Java Others Total Submission s 598 Accepted Sub
  • HDU 6298(数学)

    题意是给出一个数 xff0c 找出这个数的三个因子且这三个因子的和等于这个数 xff0c 输出满足条件的乘积最大的一组因子的乘积 xff0c 如果不存在这样的因子 xff0c 就输出 1 第一次 wa 了 xff0c 因为把题目中的 x n
  • HDU 1880 魔咒词典(Hash+二分)

    题目链接 哈利波特在魔法学校的必修课之一就是学习魔咒 据说魔法世界有100000种不同的魔咒 xff0c 哈利很难全部记住 xff0c 但是为了对抗强敌 xff0c 他必须在危急时刻能够调用任何一个需要的魔咒 xff0c 所以他需要你的帮助
  • hdu 5119(dp题)

    题目链接 xff1a http acm hdu edu cn showproblem php pid 61 5119 题目 xff1a Matt has N friends They are playing a game together
  • hdu 3700 cat

    Cat Time Limit 2000 1000 MS Java Others Memory Limit 32768 32768 K Java Others Total Submission s 181 Accepted Submissio
  • HDU 3700 Cat

    Cat Time Limit 2000 1000 MS Java Others Memory Limit 32768 32768 K Java Others Total Submission s 451 Accepted Submissio
  • HDU 1085

    题意 xff1a 有1 2 5三数 xff0c 你赋予他们各自的数量 xff0c 求他们所不能组成的最小数 分析 xff1a 首先想到暴力 xff0c 两层循环 暴力超时 xff0c 再寻他法 O n 2 include 34 cstdio
  • hdu 1669 Jamie's Contact Groups

    Jamie 39 s Contact Groups Time Limit 15000 7000 MS Java Others Memory Limit 65535 65535 K Java Others Total Submission s
  • HDOJ/HDU 1085 母函数 Holding Bin-Laden Captive!

    Holding Bin Laden Captive Time Limit 2000 1000 MS Java Others Memory Limit 65536 32768 K Java Others Total Submission s
  • 2017icpc沈阳站_M_HDU-6229_(思维)

    链接 xff1a http acm hdu edu cn showproblem php pid 61 6229 题意 xff1a 给一个矩阵上面有一些坏点 xff0c 坏点不能走 xff0c 起点是 0 0
  • 2017icpc沈阳站_M_HDU-6229_(思维)

    链接 xff1a http acm hdu edu cn showproblem php pid 61 6229 题意 xff1a 给一个矩阵上面有一些坏点 xff0c 坏点不能走 xff0c 起点是 0 0
  • [JAVA][2013蓝桥杯预赛 JAVA本科B组][有理数类]

    标题 有理数类 有理数就是可以表示为两个整数的比值的数字 一般情况下 我们用近似的小数表示 但有些时候 不允许出现误差 必须用两个整数来表示一个有理数 这时 我们可以建立一个 有理数类 下面的代码初步实现了这个目标 为了简明 它只提供了加法
  • hdu 1059 Dividing

    Problem acm hdu edu cn showproblem php pid 1059 题意 6 种宝石 价值分别是 1 到 6 分别给出 6 种宝石的数量 问能不能分成等价值的两堆 分析 多重背包 主要是记录下多重背包的写法 对每
  • hdu 1074 Doing Homework

    Problem acm hdu edu cn showproblem php pid 1074 题意 n 份作业 分别给出名字 完成所需时间 cost 最迟上交时间 deadline 作业每迟交一天扣一分 问最少的扣分数 Analysis
  • hdu 6127 Hard challenge

    Problem acm hdu edu cn showproblem php pid 6127 Meaning 平面上有 n 个不重合的点 任意三点不共线 任意两点所在直线不经原点 每个点有个 value 任意两个点连出的线段的 value
  • hdu 4405 Aeroplane chess

    Problem acm hdu edu cn showproblem php pid 4405 vjudge net contest 151678 problem R Reference bbs csdn net topics 380193
  • hdu 1069 Monkey and Banana

    Problem acm hdu edu cn showproblem php pid 1069 Reference www cnblogs com kuangbin archive 2011 08 04 2127291 html 题意 给
  • hdu 5818 Joint Stacks 2016 Multi-University 7

    Problem acm hdu edu cn showproblem php pid 5818 官方题解 bestcoder hdu edu cn blog 2016 multi university training contest 7
  • hdu 6181 Two Paths

    Problem acm hdu edu cn showproblem php pid 6181 Reference Dijkstra应用之次短路 2017 Multi University Training Contest 10 1011
  • HDU1085 Holding Bin-Laden Captive!

    Problem Description We all know that Bin Laden is a notorious terrorist and he has disappeared for a long time But recen

随机推荐

  • Matlab日记

    Matlab中对clear函数赋值后如何清除变量 xff1f 方法很多 xff0c 一般用 builtin clear b u i l t i n 执 行 内 建 的 函 数 b u i l
  • QT_Windows_命令行下编译,发布

    本文所使用到的资源链接 xff1a 1 所有QT版本镜像下载 2 单文件制作封装工具Engima Virtual Box 环境配置 xff1a 报如下错 xff0c 参考这个 在我这里是因为 xff1a 系统的环境变量的目录中有几个版本不同
  • 容斥原理详解

    翻译 xff1a vici 64 cust 对容斥原理的描述 容斥原理是一种重要的组合数学方法 xff0c 可以让你求解任意大小的集合 xff0c 或者计算复合事件的概率 描述 容斥原理可以描述如下 xff1a 要计算几个集合并集的大小 x
  • 2018ACM/ICPC全国邀请赛(江苏) 总结

    抱憾打铁 整理了一下今天的思路 xff0c 记录如下 开始时我先开的A题 xff0c 我感觉是模拟 xff0c 和lqs讨论了一下 xff0c 感觉会T xff0c 就想其他方法了 开始wjj开的B xff0c 他说感觉是推个公式 xff0
  • HDU 1002 Java大数

    题意很简单输出 a 43 b a 43 b 只不过 a a 和 b b 都很大 xff0c 需要处理大数问题 Java大数解决方法 xff0c 详见代码 xff1a import java io import java util impor
  • broadcom OF-DPA

    https www broadcom com products ethernet connectivity software of dpa http broadcom switch github io of dpa doc html OFD
  • 【论文笔记】Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition...

    Spatial Temporal Graph Convolutional Networks for Skeleton Based Action Recognition 2018 01 28 15 45 13 研究背景和动机 xff1a 行人
  • Windows下GCC编译环境中文乱码解决方案

    转载声明 xff1a 来自https blog csdn net MyLibs article details 27913281 在编译参数中增加以下两条指令 xff1a fexec charset 61 gbk finput charse
  • C++ 读入优化与输出优化 模板

    来自 xff1a https blog csdn net liyizhixl article details 54412459 简介 C 43 43 是一种神奇的编程语言 自然 xff0c 读入和输出也有着许多种形式 xff1a 如 xff
  • RMQ(range minimum/maximum query)即查询区间最大最小值。

    转载来自 https www cnblogs com yyxayz p 4109390 html 对于求区间最大最小值 xff0c 我们自然而然就想到了一个O xff08 n xff09 时间复杂度的算法 xff0c 但是如果询问有很多呢
  • 数论小知识点总结

    m i 61 1 g c d m i 61 d m d m d i 61 1 m g
  • 牛客国庆集训派对Day1(A C E L)

    链接 xff1a https www nowcoder com acm contest 201 question 牛客国庆集训派对Day1 A Tobaku Mokushiroku Kaiji xff08 水题 xff09 C Utawar
  • 牛客国庆集训派对Day2(A F H)

    链接 xff1a https www nowcoder com acm contest 202 question 牛客国庆集训派对Day2 A 矩阵乘法 xff08 分块 xff09 F 平衡二叉树 xff08 数据结构 xff09 H 卡
  • Git learn

    分布式版本控制系统 Git https git scm com 一 初始化 init xff0c 添加 add 到暂存区 stage xff0c 提交 commit 到版本库 master 二 工作区 xff0c 版本库 状态 status
  • 牛客国庆集训派对Day4(A D I J)

    链接 xff1a https www nowcoder com acm contest 204 question 牛客国庆集训派对Day4 A 深度学习 xff08 思维水题 xff09 D 最小生成树 xff08 思维 xff09 I 连
  • Codeforces Round #513 by Barcelona Bootcamp (rated, Div. 1 + Div. 2) (A B C)

    链接 xff1a http codeforces com contest 1060 Codeforces Round 513 A Phone Numbers xff08 水题 xff09 B Maximum Sum of Digits xf
  • 计算几何 (POJ1127 、 )

    计算几何 1 判断线段是否相交 1 判断线段是否相交 在不需求出交点 xff0c 只需判断两条线段是否相交 xff0c 可以使用 1 快 速 排 斥 实
  • oled显示乱码解决方法

    有时候oled偶尔发生乱码 xff0c xff08 大多数时候正常 xff0c 偶尔乱码 原因分析 xff0c 由于显示oled时使用的i2c连线较长 xff0c 会出现更大的电感 进而出现振铃现象 解决办法 在时钟线和数据线中串联100欧
  • 次短路

    次短路 概念 xff1a 次短路是相对于最短路的 xff0c 简单来说就是第二短的路径 方法 xff1a d i j k s t r
  • 2017icpc沈阳站_M_HDU-6229_(思维)

    链接 xff1a http acm hdu edu cn showproblem php pid 61 6229 题意 xff1a 给一个矩阵上面有一些坏点 xff0c 坏点不能走 xff0c 起点是 0 0