BZOJ 1967 [Ahoi2005]CROSS 穿越磁场

啊。。比较水的一题。先离散化,然后直接跑一遍最短路就可以了。

注意它可以从离散化后的边缘走。。因此要处理一下边缘(可以看我代码,代码中用注释标注了)。。因为这个WA了一发

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const size_t Max_N(105);
typedef pair<int, int> pil;

const int dx[] = {+1, -1, +0, +0};
const int dy[] = {+0, +0, +1, -1};

struct square
{
    int sx, sy, tx, ty;
};

int N;
square V[Max_N];
int SX, SY, TX, TY;
int A, B;
double X[Max_N * 3], Y[Max_N * 3];

bool Map[Max_N * 3][Max_N * 3];

int lookup(const int &n, const double Array[], const double &Key)
{
    int l(1), r(n + 1), mid;
    while (l < r)
    {
        mid = l + ((r - l) >> 1);
        if (Array[mid] == Key)
            return mid;
        if (Array[mid] < Key)
            l = mid + 1;
        else
            r = mid;
    }
    return -1;
}

void init()
{
    int C;
    scanf("%d", &N);
    for (int i = 1;i <= N;++i)
    {
        scanf("%d%d%d", &V[i].sx, &V[i].sy, &C);
        V[i].tx = V[i].sx + C, V[i].ty = V[i].sy + C;
        X[i * 3 - 2] = V[i].sx, X[i * 3 - 1] = V[i].tx, X[i * 3] = (V[i].sx + V[i].tx) / 2.0;
        Y[i * 3 - 2] = V[i].sy, Y[i * 3 - 1] = V[i].ty, Y[i * 3] = (V[i].sy + V[i].ty) / 2.0;
    }
    scanf("%d%d%d%d", &SX, &SY, &TX, &TY);
    X[N * 3 + 1] = SX, X[N * 3 + 2] = TX, X[N * 3 + 3] = (SX + TX) / 2.0;
    Y[N * 3 + 1] = SY, Y[N * 3 + 2] = TY, Y[N * 3 + 3] = (SY + TY) / 2.0;
}

void make_graph()
{
    sort(X + 1, X + 1 + N * 3 + 3);
    sort(Y + 1, Y + 1 + N * 3 + 3);
    A = (unique(X + 1, X + 1 + N * 3 + 3) - X) - 1;
    B = (unique(Y + 1, Y + 1 + N * 3 + 3) - Y) - 1;
    for (int i = 1;i <= N;++i)
    {
        V[i].sx = lookup(A, X, V[i].sx * 1.0), V[i].sy = lookup(B, Y, V[i].sy * 1.0);
        V[i].tx = lookup(A, X, V[i].tx * 1.0), V[i].ty = lookup(B, Y, V[i].ty * 1.0);
    }
    SX = lookup(A, X, SX * 1.0), SY = lookup(B, Y, SY * 1.0);
    TX = lookup(A, X, TX * 1.0), TY = lookup(B, Y, TY * 1.0);
    for (int i = 1;i <= N;++i)
    {
        for (int j = V[i].sy;j <= V[i].ty;++j)
            Map[V[i].sx][j] = Map[V[i].tx][j] = true;
        for (int j = V[i].sx;j <= V[i].tx;++j)
            Map[j][V[i].sy] = Map[j][V[i].ty] = true;
    }
}

int Dist[Max_N * 3][Max_N * 3];
bool In_Q[Max_N * 3][Max_N * 3];

void SPFA()
{
    ++A, ++B;//处理边缘
    memset(Dist, 0X3F, sizeof(Dist));
    queue<pil> Q;
    Q.push(make_pair(SX, SY));
    Dist[SX][SY] = 0, In_Q[SX][SY] = true;
    int TopX, TopY, ToX, ToY;
    while (Q.size())
    {
        TopX = Q.front().first, TopY = Q.front().second;
        In_Q[TopX][TopY] = false;
        Q.pop();
        for (int k = 0;k != 4;++k)
        {
            ToX = TopX + dx[k], ToY = TopY + dy[k];
            if (!(ToX >= 1 && ToX <= A && ToY >= 1 && ToY <= B))
                continue;
            if (Dist[ToX][ToY] > Dist[TopX][TopY] + Map[ToX][ToY])
            {
                Dist[ToX][ToY] = Dist[TopX][TopY] + Map[ToX][ToY];
                if (!In_Q[ToX][ToY])
                {
                    In_Q[ToX][ToY] = true;
                    Q.push(make_pair(ToX, ToY));
                }
            }
        }
    }
    printf("%d", Dist[TX][TY]);
}

int main()
{
    init();
    make_graph();
    SPFA();
    return 0;
}

BZOJ 1967

时间: 2024-11-07 02:17:25

BZOJ 1967 [Ahoi2005]CROSS 穿越磁场的相关文章

BZOJ 1967 Ahoi2005 CROSS 穿越磁场 FloodFill+BFS

题目大意:给定平面上的n个正方形,求某个点到另一个点至少穿过多少个边界 一开始想对于每个正方形判断一下起点和终点是否在同一侧= = 但是反例显然 考虑到n<=100,可以离散化一下,然后用Floodfill标记每块区域 然后跑最短路就行了--由于边权都是1,所以用BFS就能搞出最短路了 连边连挂了调了半宿-- #include <cstdio> #include <cstring> #include <iostream> #include <algorith

BZOJ 1968: [Ahoi2005]COMMON 约数研究

1968: [Ahoi2005]COMMON 约数研究 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 2032  Solved: 1537[Submit][Status][Discuss] Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和. Sample Input 3 Sample Output 5 HINT Source Day2 [

BZOJ 1969: [Ahoi2005]LANE 航线规划( 树链剖分 )

首先我们要时光倒流, 倒着做, 变成加边操作维护关键边. 先随意搞出一颗树, 树上每条边都是关键边(因为是树, 去掉就不连通了)....然后加边(u, v)时, 路径(u, v)上的所有边都变成非关键边了, 因为形成了环, 环上任意2点有2条路径...下图, 加上蓝色的边, 红色x的边就变成了非关键边. 所以树链剖分维护一下...时间复杂度O(NlogN+MlogM+Qlog^2N), 可以AC. 翻了翻ZY的标解:“动态维护树+最近公共祖先查询”....复杂度是O(NlogN+M+QlogN)

BZOJ 1968: [Ahoi2005]COMMON 约数研究(新生必做的水题)

1968: [Ahoi2005]COMMON 约数研究 Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 2351  Solved: 1797 [Submit][Status][Discuss] Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和. Sample Input 3 Sample Output 5 HINT Source Day2

BZOJ 1968: [Ahoi2005]COMMON 约数研究 水题

1968: [Ahoi2005]COMMON 约数研究 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1968 Description Input 只有一行一个整数 N(0 < N < 1000000). Output 只有一行输出,为整数M,即f(1)到f(N)的累加和 Sample Input 3 Sample Output 5 HINT 题意 题解:

BZOJ 1968 [Ahoi2005]COMMON 约数研究:数学【思维题】

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1968 题意: 设f(x) = x约数的个数.如:12的约数有1,2,3,4,6,12,所以f(12) = 6. 给定n,问你f(1)到f(n)之和. 题解: 好多做法... (1)O(N*sqrt(N)) 纯暴力(应该过不了). 枚举i,sqrt(i)复杂度求出约数个数,更新ans. 不附代码. (2)O(N*log(N)) 若当前枚举到i,则i为i*k的一个约数(k >= 0),dp[

BZOJ 1969: [Ahoi2005]LANE 航线规划 [树链剖分 时间倒流]

题意: 一张图,删除边,求两点之间的割边数量.保证任意时刻图连通 任求一棵生成树,只有树边可能是割边 时间倒流,加入一条边,就是两点路径上的边都不可能是割边,区间覆盖... 然后本题需要把边哈希一下,手写哈希比map快很多 貌似还有一种不用树剖的做法,不管了 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; co

BZOJ 1968 AHOI2005 COMMON 约数研究 线性筛

题目大意:求n以内所有数的约数个数和 100W,n√n别想了 线性筛可以处理,对于每个数记录最小质因数的次数 令factoral[i]为i的因数个数 cnt[i]为i的最小质因数的次数 若i为质数 则factoral[i]=2 cnt[i]=1 若i%prime[j]!=0 则factoral[prime[j]*i]=factorial[i]*2 cnt[prime[j]*i]=1 若i%prime[j]==0 则factorial[prime[j]*i]=factorial[i]/(cnt[i

BZOJ 1965 AHOI2005 SHUFFLE 洗牌 数论

题目大意:给定偶数张牌,问m次洗牌之后第l张牌是多少 x*2^m==l (mod n+1) x=(n/2+1)^m*l mod n+1 快速幂+快速乘233 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MOD (n+1) using namespace std; typedef unsigned long long ll; long