zoukankan      html  css  js  c++  java
  • XDOJ 1202: The Offer

    XDOJ 1202: The Offer - Lunatic

    题目链接:http://acm.xidian.edu.cn/problem.php?id=1202

    题目大意:给定一个$n imes m$的网格图,每个格子上有值$h[i][j]$。有两种移动方式:1.移动到相邻的格子(代价为原位置和移动后位置上的值之和);2.在给定的$k$个矩形内,若两个格子值相差不超过$p[k]$,则可互相移动(代价为$t[k]$)。现给定起点坐标和终点坐标,问最小代价。

    Dijkstra

    关键在于建图,建好图后直接跑最短路就好了。

    给每个矩形设$3 imes 101$个虚点,将该矩形内$h[i][j]=x$的点分别与三个虚点$d_x^1,d_x^2,d_x^3$相连(其中$d_x^1$指向点$(i,j)$(边长为$0$),点$(i,j)$指向$d_x^2$(边长为$0$),$d_x^3$与点$(i,j)$互相连接(边长为$t[k]$)),最后将符合条件($fabs(a-b)  leqslant p[k]$)的$d_a^1$点与$d_b^2$点相连接(边长为$2 imes t[k]$)。

    (考虑到$t[k]$可能不能被$2$整除,将所有边长乘$2$,再将结果除$2$)。

    具体结构如下图所示(请叫我灵魂画师,不接受批评歇歇):

    by barriery

    最后将相邻格子互相连边,跑下Dijkstra即可。

    建图复杂度为$O(rn^2MAX{h[i][j]})$,故总复杂度为$O(rn^2MAX{h[i][j]}+n^2logn)$.

    代码如下:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <vector>
      4 #include <queue>
      5 #define N 105
      6 #define R 15
      7 #define X first
      8 #define Y second
      9 using namespace std;
     10 typedef long long ll;
     11 typedef pair<ll,ll> P;
     12 const ll inf=1000000000000000LL;
     13 ll CASE,mp[N][N],n,m,r,t[R],p[R],dis[N*N+3*R*N];
     14 bool vis[N*N+3*R*N];
     15 P a[R],b[R],S,T;
     16 struct edge{
     17     ll to,w;
     18     edge(ll T,ll W){to=T;w=W;}
     19 };
     20 struct node{
     21     ll u,d;
     22     node(ll U,ll D){u=U;d=D;}
     23     bool operator < (const node x)const{return d>x.d;}
     24 };
     25 vector<edge>e[N*N+3*R*N];
     26 priority_queue<node>q;
     27 void init(){
     28     for(ll i=0;i<n*m+3*101*r;++i)e[i].clear();
     29     for(ll k=0;k<r;++k){
     30         ll bs=n*m+k*3*101;
     31         for(ll i=a[k].X;i<=b[k].X;++i){
     32             for(ll j=a[k].Y;j<=b[k].Y;++j){
     33                 ll d1=bs+3*mp[i][j],d2=bs+3*mp[i][j]+1,d3=bs+3*mp[i][j]+2;
     34                 e[d1].push_back(edge(i*m+j,0));
     35                 e[i*m+j].push_back(edge(d2,0));
     36                 e[d3].push_back(edge(i*m+j,t[k]));
     37                 e[i*m+j].push_back(edge(d3,t[k]));
     38             }
     39         }
     40         for(ll i=0;i<=100;i++){
     41             for(ll j=i;j<=i+p[k]&&j<=100;j++){
     42                 e[bs+3*i+1].push_back(edge(bs+3*j,2*t[k]));
     43                 e[bs+3*j+1].push_back(edge(bs+3*i,2*t[k]));
     44             }
     45         }
     46     }
     47     for(ll i=0;i<n;++i){
     48         for(ll j=0;j<m;++j){
     49             int k=i*m+j;
     50             if(i!=0)e[k].push_back(edge((i-1)*m+j,2*(mp[i][j]+mp[i-1][j])));
     51             if(i!=n-1)e[k].push_back(edge((i+1)*m+j,2*(mp[i][j]+mp[i+1][j])));
     52             if(j!=0)e[k].push_back(edge(i*m+j-1,2*(mp[i][j]+mp[i][j-1])));
     53             if(j!=m-1)e[k].push_back(edge(i*m+j+1,2*(mp[i][j]+mp[i][j+1])));
     54         }
     55     }
     56 }
     57 ll dijkstra(ll s,ll d){
     58     ll tot=n*m+3*101*r;
     59     for(ll i=0;i<tot;++i){
     60         dis[i]=inf;
     61         vis[i]=0;
     62     }
     63     dis[s]=0;
     64     while(!q.empty())q.pop();
     65     q.push(node(s,0));
     66     while(!q.empty()){
     67         node t=q.top();q.pop();
     68         ll u=t.u;
     69         if(vis[u])continue;
     70         vis[u]=1;
     71         for(ll i=0;i<(ll)e[u].size();++i){
     72             ll v=e[u][i].to,w=e[u][i].w;
     73             if(dis[u]+w<dis[v]){
     74                 dis[v]=dis[u]+w;
     75                 q.push(node(v,dis[v]));
     76             }
     77         }
     78     }
     79     return dis[d];
     80 }
     81 int main(void){
     82     scanf("%lld",&CASE);
     83     while(CASE--){
     84         scanf("%lld%lld%lld",&n,&m,&r);
     85         for(ll i=0;i<n;++i)
     86             for(ll j=0;j<m;++j)
     87                 scanf("%lld",&mp[i][j]);
     88         for(ll i=0;i<r;++i){
     89             scanf("%lld%lld",&a[i].X,&a[i].Y);
     90             scanf("%lld%lld",&b[i].X,&b[i].Y);
     91             a[i].X--,a[i].Y--,b[i].X--,b[i].Y--;
     92             scanf("%lld%lld",&t[i],&p[i]);
     93         }
     94         scanf("%lld%lld",&S.X,&S.Y);
     95         scanf("%lld%lld",&T.X,&T.Y);
     96         S.X--,S.Y--,T.X--,T.Y--;
     97         init();
     98         ll ans=dijkstra(S.X*m+S.Y,T.X*m+T.Y)/2;
     99         printf("%lld
    ",ans);
    100     }
    101 }
  • 相关阅读:
    ajax函数说明
    rem移动端适配
    使用微信打开网页,弹出软键盘时遇到的兼容问题
    jquery
    今天才发现博客园加密了的文章其实还是能看到的,我tm哪里还敢在这上面写东西,吓死爹了。
    Solr的原理及在项目中的使用实例
    Lucene入门
    oracle包package的使用
    oracle自定义split分割函数
    Zookeeper到底是干嘛的
  • 原文地址:https://www.cnblogs.com/barrier/p/6756159.html
Copyright © 2011-2022 走看看