萃香抱西瓜

伊吹萃香(Ibuki Suika)正在魔法之森漫步,突然,许多西瓜(Suika)从四周飞来,划出了绚丽的轨迹。虽然阵势有点恐怖,但她还是决定抱走一些西瓜。

题目描述

萃香所处的环境被简化为一个长为h,宽为w的网格平面。X坐标范围为[1,w],y坐标范围为[1,h]。

她初始(第1个时刻)站在坐标为sx,sy的方格。

西瓜可能在任意一个方格出现,在每个时间单位,它们可能向任何一个方向移动,也可能静止不动。西瓜的位置和移动的轨迹是已知的。西瓜的总数为n个,但只有m个西瓜可以被萃香抱走,因为其他都太大了,可能会砸伤她。

整个过程会持续T个时刻。萃香希望可以抱走全部的m个西瓜,并且在任何时候避免与任何一个过大的西瓜处在同一位置。抱走的方式为在某个时刻,与该西瓜处于同一位置。另外,由于萃香不愿耗费过多体力到处乱跑,她每个时刻可以选择静止不动,也可以选择移动到相邻的四个格子之一,只要不越出环境边界。如果选择移动到相邻格子,则算作移动了一次。(第1个时刻萃香刚站定,无法移动)

在每个时刻,如果萃香选择移动,可以认为萃香与西瓜同时从原来的位置移到了新的位置,没有先后顺序。

萃香想要知道,不被任何一个大西瓜砸中,并得到所有的m个小西瓜的情况下,最少需要移动多少次。

输入输出格式

输入格式:

第一行五个整数h,w,T,sx,sy,含义见题目描述。

第二行两个整数n,m,含义见题目描述。

接下来n段数据,每一段描述了一个西瓜的出现位置,时间,移动方式,是否可以被抱走等内容,具体如下:

首先一行,两个整数t1,t2,表示西瓜在t1时刻出现, t2时刻消失。若t2=T+1,表示西瓜在最后一个时刻也不消失。保证西瓜至少存在一个时刻。

接下来一行一个整数a,只能为0或1,0表示这个西瓜需要避开,1表示这个西瓜需要抱走。数据保证需要抱走的西瓜恰好有m个。

接下来t2-t1行,每一行两个整数x,y,顺序描述了从t1时刻到t2-1时刻,该西瓜的坐标。西瓜的移动不一定是连续的,并且是一瞬间完成的,所以无需考虑萃香是否站在了移动路径上。

输出格式:

如果萃香在整个T时刻内无法避免被大西瓜砸中或者无法收集到所有m个小西瓜,输出-1,否则输出一个整数,表示萃香需要移动的最少次数。

输入输出样例

输入样例#1:
5 5 10 3 3
1 1
1 11
1
3 4
5 2
3 5
1 1
5 4
3 4
2 1
1 1
1 1
5 5
输出样例#1:
1

说明

样例说明:第2~4个时刻萃香站着不动,在第6个时刻,西瓜出现在萃香旁边,萃香移动到(3,4)位置即可抱走这个西瓜。

数据范围和提示:

子任务可能出现两种特殊性质A和B

A: 所有西瓜t1=1,t2=T+1

所有西瓜全程都静止在原地,不会发生移动。

B:m=0

共有10个子任务。

对于子任务1,具有特殊性质A和B

对于子任务2~3,仅具有特殊性质A

对于子任务4~5,仅具有特殊性质B

对于子任务6~10,不具有任何一个特殊性质。

对于全部子任务

1<=所有横坐标范围<=w
1<=所有纵坐标范围<=h
1<=h,w<=5
1<=T<=100
1<=t1<=T
2<=t2<=T+1
t1<t2
1<=n<=20
0<=m<=10
m<=n

一个位置不会同时出现两个或以上西瓜。

子任务1:所有西瓜始终出现且不动,并且没有要抱走的。

 

解法:只需要判断初始位置是否被大西瓜挡住,挡住输出-1,否则输出0即可

 

子任务2~3:所有西瓜始终出现且不动。

 

解法:由于要抱走的西瓜最多为10个,考虑用长度为10的0/1串来表示某个西瓜是否已经获取。状压spfa或dp即可解决。

 

子任务4~5:没有需要抱走的西瓜

 

解法:将时间看做一个维度,构建好三维的地图,把西瓜看做障碍,做三维的最短路或dp即可。

正解:bfs+状态压缩dp

状态转移:dist[x'][y'][t][k']=min(dist[x][y][t-1][k])

dist[x][y][t][k]表示在(x,y),t时,取西瓜的状态k,k为一个二进制数

事先处理出(x,y),t时有无西瓜,是哪个西瓜。

接下来就是bfs过程的实现

注意的是这里用了一个小技巧:

当所要记录的状态有多个,且都很小时,可以把它们分配在一个数的不同位,用一个数表示。如123/456/7/8表示(7,8)时t=456,k为123的二进制

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 int mp[6][6][103];
 7 int dist[6][6][103][1024];
 8 bool vis[6][6][103][1024];
 9 const int dx[5]={0,1,-1,0,0};
10 const int dy[5]={0,0,0,1,-1};
11 int w,h,T,sx,sy,cnt;
12 int n,m;
13 queue<int> q;
14 void spfa()
15 {
16     q.push(1*100+sx*10+sy);
17     memset(dist,0x3f,sizeof(dist));
18     dist[sx][sy][1][0]=0;
19     while(!q.empty())
20     {
21         int now=q.front();
22         q.pop();
23         int nows=now/100000;
24         int nowt=(now%100000)/100;
25         int nowx=(now%100)/10;
26         int nowy=now%10;
27         //cout<<nowx<<' '<<nowy<<endl;
28         vis[nowx][nowy][nowt][nows]=0;
29         if (nowt==T)
30          continue;
31         for (int i=0;i<=4;i++)
32           {
33               int nextx=nowx+dx[i];
34               int nexty=nowy+dy[i];
35               int nextt=nowt+1;
36               int nexts;
37                if (nextx<1||nextx>w) continue;
38                 if (nexty<1||nexty>h) continue;
39                 if (mp[nextx][nexty][nextt]==10000) continue;
40                 if (mp[nextx][nexty][nextt]==0x3f3f3f3f) nexts=nows;
41                 else 
42                 {
43                     nexts=nows|(1<<(mp[nextx][nexty][nextt]-1));
44                 }
45               if (dist[nowx][nowy][nowt][nows]+(bool)(i)<dist[nextx][nexty][nextt][nexts])
46             {
47              dist[nextx][nexty][nextt][nexts]=dist[nowx][nowy][nowt][nows]+(bool)(i);
48               if (vis[nextx][nexty][nextt][nexts]==0)
49               {
50                   vis[nextx][nexty][nextt][nexts]=1;
51                   q.push(nexts*100000+nextt*100+nextx*10+nexty);
52               }
53             }
54           }
55     }
56 }
57 int main()
58 {
59     scanf("%d%d%d%d%d",&w,&h,&T,&sx,&sy);
60     scanf("%d%d",&n,&m);
61     memset(mp,0x3f,sizeof(mp));
62     for(int i=1;i<=n;i++)
63     {
64         int t1,t2,a;
65         scanf("%d%d",&t1,&t2);
66         scanf("%d",&a);
67         if(a==0)a=10000;
68         else a=++cnt;
69         for(int i=t1;i<t2;i++)
70         {
71             int x,y;
72             scanf("%d%d",&x,&y);
73             mp[x][y][i]=a;
74         }
75     }
76     if(mp[sx][sy][1]==10000)
77     {
78         printf("-1\n");
79         return 0;
80     }
81     spfa();
82     int ans=0x3f3f3f3f;
83     for(int i=1;i<=w;i++)
84         for(int j=1;j<=h;j++)
85             ans=min(ans,dist[i][j][T][(1<<m)-1]);
86     if(ans==0x3f3f3f3f)ans=-1;
87     printf("%d\n",ans);
88     return 0;
89 }

 

posted @ 2017-07-05 16:13  Z-Y-Y-S  阅读(462)  评论(0编辑  收藏  举报