USACO 2017 February Contest Gold T1: Why Did the Cow Cross the Road

题目大意

奶牛们为什么要穿马路?一个原因只是因为FJ的牧场的路实在是太多了,使得奶牛们每天不得不穿梭在许许多多的马路中央。

FJ的牧场可以看作是一块N×N 的田地(3N100),N1 条南北向的道路和 N1 条东西向的道路贯穿整个牧场,同时是每块田野的分界线。牧场的最外面是一圈高大的栅栏以防止奶牛离开牧场。

Bessie只要穿过分离两块田野的道路,就可以从任何田野移动到与其相邻的田野里去(北,东,南或西)。当然,Bessie穿过每一条马路都是需要 T 时间的。(0T1,000,000)

有一天,FJ邀请Bessie来他家下棋,Bessie从牧场的西北角出发,FJ的家在牧场的东南角。因为Bessie在中途可能会饿,所以她每走过三块田野就要停下来,享用她所在田野上的新鲜的牧草(不包括Bessie的出发点,但是可能会包括终点FJ的家),

牧场上有些田野的牧草长得比其他地方茂盛,所以Bessie对应的停留时间也会变长。

请帮帮Bessie计算出她走到FJ家的最短时间。

题目分析

观察数据范围,N最大只有100,所以最多有1e4个点。

因为要求最短时间,而点数太多,所以不考虑搜索,考虑使用最短路。

然而每走三块田地要停下来,所以,我们把一个点与从它走三步所能到达的点连边。然后跑个最短路就行。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int MAXN=2e4+10;
 5 const ll Inf=1e18+7;
 6 struct Edge{
 7     int to,nxt;
 8     ll dis;
 9 }e[MAXN<<4];
10 int cnt,head[MAXN];
11 inline void add_edge(int u,int v,ll d){
12     e[++cnt].to=v;e[cnt].nxt=head[u];e[cnt].dis=d;head[u]=cnt;
13 }
14 
15 struct Node{
16     ll dis;
17     int pos;
18     inline bool operator<(const Node &x)const{
19         return x.dis<dis;
20     } 
21 };
22 
23 int n;
24 ll t,g[105][105];
25 int dx[20]={-1,-2,-3,-1,-2,0,1,2,1,2,3,0,0,1,0,-1};
26 int dy[20]={-2,-1,0,2,1,-3,-2,-1,2,1,0,3,1,0,-1,0};
27 ll dis[MAXN],ans;
28 bool vis[MAXN];
29 inline int Id(int x,int y){return (x-1)*n+y;}
30 priority_queue<Node> q;
31 inline void Dijkstra(){
32     for(int i=1;i<=n*n;++i)
33         dis[i]=Inf;
34     //puts("");
35     //for(int i=1;i<=n;++i){
36     //    for(int j=1;j<=n;++j)
37     //        printf("%lld ",dis[Id(i,j)]); 
38     //    printf("\n");
39     //}
40     q.push((Node){(ll)0,Id(1,1)});
41     dis[Id(1,1)]=0;
42     while(!q.empty()){
43         Node fa=q.top();
44         int x=fa.pos;
45         q.pop();
46         if(vis[x]) continue;
47         vis[x]=1;
48         for(int i=head[x],y;i;i=e[i].nxt){
49             y=e[i].to;
50             if(dis[y]>dis[x]+e[i].dis){
51                 dis[y]=dis[x]+e[i].dis;
52                 q.push((Node){dis[y],y});
53             }
54         }
55     }
56 }
57 int main(){
58     scanf("%d%lld",&n,&t);
59     for(int i=1;i<=n;++i)
60         for(int j=1;j<=n;++j)
61             scanf("%lld",&g[i][j]);
62     for(int i=1;i<=n;++i)
63         for(int j=1;j<=n;++j){
64             for(int k=0;k<16;++k){
65                 if(i+dx[k]>=1&&i+dx[k]<=n&&j+dy[k]>=1&&j+dy[k]<=n){
66                     add_edge(Id(i,j),Id(i+dx[k],j+dy[k]),3*t+g[i+dx[k]][j+dy[k]]);
67                     //cout<<3*t+g[i+dx[k]][j+dy[k]]<<' '<<i+dx[k]<<' '<<j+dy[k]<<endl;
68                 }
69             }
70         }
71     Dijkstra();
72     ans=Inf;
73     for(int i=1;i<=n;++i)
74         for(int j=1;j<=n;++j)
75             if(2*n-i-j<3)
76                 ans=min(ans,dis[Id(i,j)]+(ll)t*(2*n-i-j));
77 //    for(int i=1;i<=n;++i){
78 //        for(int j=1;j<=n;++j)
79 //            printf("%lld ",dis[Id(i,j)]); 
80 //        printf("\n");
81 //    }
82     printf("%lld\n",ans);
83     return 0;
84 }

 

posted @ 2019-07-22 21:20  LI_dox  阅读(233)  评论(0编辑  收藏  举报