您的位置:首页 > 其它

Wannafly 2018年全国多校算法寒假训练营练习比赛(第四场) G 老子的意大利炮昵

2018-03-12 23:41 821 查看
链接

题目描述

自攻打过太原县城以后,李云龙这意大利炮就使用的越发的顺手了,指哪打哪也是绝不含糊,于是小野队长开始疯狂打击独立团炮兵营,为了锻炼士兵移动意大利炮的能力,李团长开始给炮兵营进行特训,众(wo)所(xia)周(bian)知(de),意大利炮可由炮管,车轮,炮弹三部分组成,现在李团长在洋村设立阵地,分别把炮管,车轮,炮弹放在三个不同的地方,每一部分的重量不同,所以运输的速度也不相同。团长说:你谁有能耐最快把这意大利炮组装好然后运到我面前,老子就赏他半斤地瓜烧,和尚听了乐坏了,但是他不知道怎么才能使时间最快,你能帮帮他么?
零件只要拿起,就不能放下,所以说不存在在a点拿起,b点放下再去取别的零件一说。默认和尚1秒走一个单位距离,并且只能向上下左右四个方向走,假设和尚现在拿着炮管,那么他每走一单位距离则需要(t1 + 1)秒,如果再拿上车轮,那么
4000
他现在每走一步则需要(t1 + t2+1)秒的时间,以此类推。点可以重复经过,路过有零件的点时,可以选择拿或者不拿。

输入描述:

第一行给定两个整数n, m代表地图大小,(1<=n, m <= 100);接下来n行每行有m个由‘#’和‘.’组成的字符,’#’代表墙,’.’代表路,和尚功夫高,可以自己或者
带着零件翻墙(不论墙多厚),但是组装好意大利炮之后就必需得走路了。地图画好之后,接下来一行有10个整数sx,sy,x1, y1, x2, y2, x3, y3, ex, ed
(都小于100)代表五个点,分别是起始点,炮管的位置,车轮的位置,炮弹的位置,李团长的位置(终点), 五个点保证不同。最后一行三个整数t1, t2, t3,
(都大于等于1,小于100),分别代表炮管,车轮,炮弹每走一单位距离需要的时间。题目保证数据合法。

输出描述:

输出一个整数并换行,代表和尚完成任务所需要的最短时间。题目保证有解。

示例1

输入

3 5
##.##
.#.#.
##.##
1 3 2 1 2 3 2 5 3 3
1 5 4

输出

34

说明

对于第一组样例,我们发现只有在2号零件也就是车轮的位置组装完才能运回到李团长的位置,所以最优解为:起始点->1号零件 –> 3号零件-> 2号零件->李团长
路线为(1,3),(2,3),(2,2),(2,1),(2,2),(2,3),(2,4),(2,5),(2,4),(2,3),(3,3)。
答案为34。


题意:你能看懂的,如果看不懂可以读三遍(开玩笑);
解题思路: 我这个解题思路有点奇葩,不知是我创造了一个新创新点,还是这题目有点水。
首先当你凑齐3个零件的时候,你就能拼装出一个意大利炮(集齐龙珠,召唤神龙)。这时候你就不能翻越墙了,你只能在地上走,而且你还能到李云龙团长那。所以你可以先给起点,零件1,零件2,零件3建图。你没听错,就是建图。
听到这,你们一定会很有疑问?这题建图有啥用啊?
我想找出从起点到任意的零件的最短距离(经过其他两个零件)。(这里就完成了一半)。
然后我们可以对每一个零件进行一次广搜,看看能不能到李云龙的位置,如果能到的话,就把这个答案记录下来。(注意,每次移动所花费的时间为t1+t2+t3+1)。然后把这三个答案进行比较取最小值,得到的就是答案。
你也可以从李云龙的位置进行搜索,这样的话终点判断多了点,广搜一遍就行了。
由于我今天有点想不出来前半段的写法,所以偷懒用了枚举。

最后希望能对你们有所帮助,一起加油。#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=110;
const int inf=0x3f3f3f3f;
int vis[maxn][maxn],n,m;
int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
char ch[maxn][maxn];
int t[3],numx[3],numy[3],sx,sy,ex,ey;
int ans[3];//每一个点到李云龙的时间
int kk[3];//从起点到 最后一个零件的所花费的时间
struct Node{
int x,y,step;
};
bool check(int x,int y){
if(x>0&&x<=n&&y>0&&y<=m) return 1;
return 0;
}
int find(int u1,int u2,int u3){
int tt=1;
int ans=0;
int temp=tt*(abs(sx-numx[u1])+abs(sy-numy[u1]));
ans+=temp;
tt+=t[u1];
temp=tt*(abs(numx[u2]-numx[u1])+abs(numy[u2]-numy[u1]));
ans+=temp;
tt+=t[u2];
temp=tt*(abs(numx[u2]-numx[u3])+abs(numy[u2]-numy[u3]));
ans+=temp;
return ans;
}
void dfs(int x1,int y1,int flag){
vis[x1][y1]=0;
queue<Node> qu;
Node np,po;
np.x=x1;np.y=y1;np.step=0;
qu.push(np);
while(!qu.empty()){
np=qu.front();
qu.pop();
if(np.x==ex&&np.y==ey){
ans[flag]=np.step;
return ;
}
vis[np.x][np.y]=np.step;
for(int i=0;i<4;i++){
int xx=np.x+dx[i];
int yy=np.y+dy[i];
if(check(xx,yy)&&vis[xx][yy]==-1&&ch[xx][yy]!='#'){
po.x=xx;po.y=yy;po.step=np.step+t[0]+t[1]+t[2]+1;
qu.push(po);
}
}
}
}
int main(){
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%s",ch[i]+1);
}
scanf("%d%d",&sx,&sy);
for(i=0;i<3;i++){
scanf("%d%d",&numx[i],&numy[i]);
}
scanf("%d%d",&ex,&ey);
for(i=0;i<3;i++) scanf("%d",&t[i]);
kk[0]=min(find(1,2,0),find(2,1,0));
kk[1]=min(find(0,2,1),find(2,0,1));
kk[2]=min(find(0,1,2),find(1,0,2));
memset(ans,-1,sizeof(ans));
for(i=0;i<3;i++){
memset(vis,-1,sizeof(vis));
dfs(numx[i],numy[i],i);
}
int sum=inf;
for(i=0;i<3;i++){
if(ans[i]!=-1){
sum=min(sum,kk[i]+ans[i]);
}
}
printf("%d\n",sum);
return 0;
}


开心,又补了一道题
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐