zoukankan      html  css  js  c++  java
  • Cave Escape

    题意:

    给定一个 (n∗m) 的格子矩阵,其中有一个格子是起点,一个格子是终点。从起点开始移动,每次能移动到有相邻边的格子中,每个格子都有一个权值 (v),若从点 ((x,y)) 移动到点 ((i,j)),且((i,j)) 点未被访问过,则可以获得 (V_{(x,y)}*V_{(i,j)}) 的收益,若移动到终点,可以选择先不出去,继续在图上乱走,问如何可以使得走出终点后获得得收益最大?(只需要输出最大收益即可)

    传送门

    分析:

    思路:不管起点在哪里,因为权值都为正数,我们要让收益最大,肯定尽量每个点都访问一遍,然后才是最大的值,所以我们可以直接建图,然后跑一遍生成树(最大),因为要让每个点访问一次。按一般的最小生成树的算法会超时。

    正解:存图是把权值作为索引,然后从大到小依次枚举。

    代码:

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>P;
    const int N=1010;
    const int M=1e4+5;
    const int maxn=2e6+10;
    int pic[N][N];
    int x[maxn];
    vector<P>dis[M];
    int n,m,sr,sc,tr,tc,p,a,b,c;
    int fa[maxn];
    void read(int &d)
    {
        d=0;
        int f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            d=(d<<3)+(d<<1)+ch-'0';
            ch=getchar();
        }
        d*=f;
    }
    int Find(int d)
    {
        if(d!=fa[d])
            return fa[d]=Find(fa[d]);
        else
            return d;
    }
    ll solve(int tol)
    {
        ll ans=0;
        int cnt=0;
        for(int i=1e4;i>=0;i--)
        {
            for(int j=0;j<dis[i].size();j++)
            {
                P t=dis[i][j];
                int u=t.first;
                int v=t.second;
                int fu=Find(u);
                int fv=Find(v);
                if(fu!=fv)
                {
                    fa[fu]=fv;
                    ans+=i;
                    cnt++;
                }
                if(cnt==n*m-1)
                    return ans;
            }
        }
    }
    int main()
    {
        int t,cas=0;
        read(t);
        while(t--)
        {
            for(int i=0;i<=1e4;i++)
                dis[i].clear();
            read(n),read(m),read(sr),read(sc),read(tr),read(tc);
            read(x[1]),read(x[2]),read(a),read(b),read(c),read(p);
            for(int i=3;i<=n*m;i++)
                x[i]=(a*x[i-1]+b*x[i-2]+c)%p;
            int tol=0;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    int t=(i-1)*m+j,tt;
                    pic[i][j]=x[t];
                    fa[t]=t;
                    if(i-1>=1)
                    {
                        tt=(i-2)*m+j;
                        dis[pic[i][j]*pic[i-1][j]].pb(make_pair(t,tt));
                    }
                    if(j-1>=1)
                    {
                        tt=(i-1)*m+j-1;
                        dis[pic[i][j]*pic[i][j-1]].pb(make_pair(t,tt));
                    }
                }
            }
            printf("Case #%d: %lld
    ",++cas,solve(tol));
        }
        return 0;
    }
    
    
  • 相关阅读:
    [AHOI2006]文本编辑器 Splay tree区间操作
    HDU-3487 Play with Chain Splay tee区间反转,移动
    HDU-4619 Warm up 2 二分匹配
    HDU-4618 Palindrome Sub-Array 暴力枚举
    HDU-4616 Game 树形DP
    HDU-4614 Vases and Flowers 线段树区间更新
    HDU-4612 Warm up 边双连通分量+缩点+最长链
    HDU-4611 Balls Rearrangement 循环节,模拟
    HDU-4605 Magic Ball Game 树状数组+离散+dfs
    HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/12941772.html
Copyright © 2011-2022 走看看