dlut1219-spfa+二维dis
2014-03-31 23:15
246 查看
题目:
DDR Ddr
DDR口头禅:
我要征服地球!
星座:魔蝎座
生日:12月22日
血型:不明
年龄:不明
生肖:不明
身高:139公分
体重:37公斤
职业:不明
兴趣:看科幻电影
宠物:龟鸟(来自DR星的小生物)
最喜欢:开UFO飙飞
最讨厌:记者用闪光照相机给它拍照
偶像:ET外星人
语言:中文
来自DANCE RACING星球的外星人,看上去有点可爱有点邪恶的样子,来到地球的原因是因为飞行器出现,由于地球人不流通DR星的货币,所以他最大的希望是赚足够多的地球货币,用以修好飞船,为此他苦学人类的商业经济学知识,凭借超人的聪明,目前他所具备的商业头脑,就是20个哈佛高材生加在一起也比不上他。
平时喜欢躲在他那小小的UFO里通过星际超时空电脑网络和远在两万光年以外DR星的网友们聊天。虽然这是外星人头一次登陆大富翁的世界,千万别小看了它呀,据说有几个邪恶组织打算捉它去做试验,但最后都以失败告终。
科学怪人最近盯上了DDR,要拿他做实验。DDR在科学怪人找到他之前尽快逃离地球,并回到DR星。DDR的飞船是由电力提供动力的,飞船可以储存一定的电量,我们记可以存储的最大电量为C。宇宙中有多个星球,每个星球中都有充电站能免费给DDR的飞船充电,这样DDR就可以在中途停下来补充电能,然后继续前进。但是我们DDR的飞船每次启动时都要消耗一个特殊的燃料,这种燃料的缩写是AC。虽然每个星球都有充电站,但并不是每个星球都有AC燃料站的。DDR的飞船最大可以存储AC的量是S。每次DDR补充电量或者AC燃料的时候都可以直接充满,而且消耗的时间可以忽略不计。DDR的飞船不能中途没电。
现在我们给出一些详细数据:
宇宙每个星球的位置由一个三维坐标来标记(x,y,z),地球的位置是(0,0,0)
从位于(x1,y1,z1)位置的星球飞到位置在(x2,y2,z2)位置的星球
需要消耗的电量:|x1-x2|+|y1-y2|+|z1-z2|
需要消耗的时间是:(max(|x1-x2|,|y1-y2|,|z1-z2|)+min(|x1-x2|,|y1-y2|,|z1-z2|))/2,向上取整(x向上取整的意思是取不小于x的最大整数)
例如:从位于(0,0,0)飞到(1,0,0)需要的时间是1,需要消耗的电量是1
DDR在出发前的AC燃料和电量都是满的。现在DDR想知道,他逃回DR星需要的最小时间是多少?
N<=1000代表宇宙中其它星球的个数
然后N行,每行4个整数,x,y,z,H
-100<=x,y,z<=100代表该星球的坐标,H代表改星球有没有AC燃料站,1代表有,0代表没有
然后是0<=C<=100,1<=S<=5意义见题目描述
然后是三个整数-100<=tx,ty,tz<=100代表DR星的位置
啊,不容易,在组长的提示下,在re和wa之间交错,我终于过了!
以电量来建边,以时间作为边权,这题的dis要用二维,第一维记录节点,第二维记录剩余次数;队列也要记录两个值:一为节点,二为剩余次数;之后找最小值的就可以了;
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const int maxn=1005;
const int Maxn=2*1002*1002;
const int INF=0x3f3f3f3f;
struct edge{
int v,w;
int next;
};
edge side[Maxn];
int head[maxn];
int N;
int top=0;
void addEdge(int from,int to,int w)
{
side[top].v=to;side[top].w=w;
side[top].next=head[from];
head[from]=top++;
}
int ac[maxn];
int x[maxn],y[maxn],z[maxn];
int inqueue[maxn];
int dis[maxn][10];
int C,S;
typedef pair<int ,int> Pair;
int spfa(int from ,int to)
{
memset(dis,INF,sizeof(dis));
memset(inqueue,0,sizeof(inqueue));
dis[from][S]=0;
inqueue[from]=1;
queue<Pair> que;
que.push(Pair(from,S));
while(!que.empty()){
int x=que.front().first,acx=que.front().second;
que.pop();
inqueue[x]=0;
if(acx==0)continue;
for(int i=head[x];i!=-1;i=side[i].next){
int y=side[i].v;
int acy;
if(ac[y]==1) acy=S;
else acy=acx-1;
if(dis[y][acy]>dis[x][acx]+side[i].w){
dis[y][acy]=dis[x][acx]+side[i].w;
if(!inqueue[y]&&acy!=0){
que.push(Pair(y,acy));
inqueue[y]=1;
}
}
}
}
/*for(int i=0;i<=N+1;i++){
for(int j=0;j<=S;j++)
printf("%d(%d):%d\n",i,j,dis[i][j]);
}*/
int MIN=INF;
for(int i=0;i<=S;i++){
MIN=min(MIN,dis[N+1][i]);
//printf("%d:%d\n",i,dis[N+1][i]);
}
return MIN;
}
int main()
{
//freopen ("int.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
memset(head,-1,sizeof(head));
x[0]=0;y[0]=0;z[0]=0;
for(int i=1;i<=N;i++){
scanf("%d%d%d%d",&x[i],&y[i],&z[i],&ac[i]);
}
scanf("%d%d",&C,&S);
scanf("%d%d%d",&x[N+1],&y[N+1],&z[N+1]);ac[N+1]=1;
top=0;
for(int i=0;i<=N+1;i++){
for(int j=1;j<=N+1;j++){
if(i!=j&&(abs(x[i]-x[j])+abs(y[i]-y[j])+abs(z[i]-z[j])<=C)){
int time=(max(abs(x[i]-x[j]),max(abs(y[i]-y[j]),abs(z[i]-z[j])))+min(abs(x[i]-x[j]),min(abs(y[i]-y[j]),abs(z[i]-z[j])))+1)/2;
//printf("%d->%d:time:%d\n",i,j,time);
addEdge(i,j,time);
addEdge(j,i,time);
}
}
}
/* for(int i=0;i<maxn;i++){
if(head[i]!=-1){
for(int x=head[i];x!=-1;x=side[x].next){
int y=side[x].v,len=side[x].w;
printf("%d->%d:%d\n",i,y,len);
}
}
}*/
int ans=spfa(0,N+1);
if(ans==INF)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}
DDR Ddr
DDR口头禅:
我要征服地球!
星座:魔蝎座
生日:12月22日
血型:不明
年龄:不明
生肖:不明
身高:139公分
体重:37公斤
职业:不明
兴趣:看科幻电影
宠物:龟鸟(来自DR星的小生物)
最喜欢:开UFO飙飞
最讨厌:记者用闪光照相机给它拍照
偶像:ET外星人
语言:中文
来自DANCE RACING星球的外星人,看上去有点可爱有点邪恶的样子,来到地球的原因是因为飞行器出现,由于地球人不流通DR星的货币,所以他最大的希望是赚足够多的地球货币,用以修好飞船,为此他苦学人类的商业经济学知识,凭借超人的聪明,目前他所具备的商业头脑,就是20个哈佛高材生加在一起也比不上他。
平时喜欢躲在他那小小的UFO里通过星际超时空电脑网络和远在两万光年以外DR星的网友们聊天。虽然这是外星人头一次登陆大富翁的世界,千万别小看了它呀,据说有几个邪恶组织打算捉它去做试验,但最后都以失败告终。
科学怪人最近盯上了DDR,要拿他做实验。DDR在科学怪人找到他之前尽快逃离地球,并回到DR星。DDR的飞船是由电力提供动力的,飞船可以储存一定的电量,我们记可以存储的最大电量为C。宇宙中有多个星球,每个星球中都有充电站能免费给DDR的飞船充电,这样DDR就可以在中途停下来补充电能,然后继续前进。但是我们DDR的飞船每次启动时都要消耗一个特殊的燃料,这种燃料的缩写是AC。虽然每个星球都有充电站,但并不是每个星球都有AC燃料站的。DDR的飞船最大可以存储AC的量是S。每次DDR补充电量或者AC燃料的时候都可以直接充满,而且消耗的时间可以忽略不计。DDR的飞船不能中途没电。
现在我们给出一些详细数据:
宇宙每个星球的位置由一个三维坐标来标记(x,y,z),地球的位置是(0,0,0)
从位于(x1,y1,z1)位置的星球飞到位置在(x2,y2,z2)位置的星球
需要消耗的电量:|x1-x2|+|y1-y2|+|z1-z2|
需要消耗的时间是:(max(|x1-x2|,|y1-y2|,|z1-z2|)+min(|x1-x2|,|y1-y2|,|z1-z2|))/2,向上取整(x向上取整的意思是取不小于x的最大整数)
例如:从位于(0,0,0)飞到(1,0,0)需要的时间是1,需要消耗的电量是1
DDR在出发前的AC燃料和电量都是满的。现在DDR想知道,他逃回DR星需要的最小时间是多少?
Input
T<=10代表测试数据个数N<=1000代表宇宙中其它星球的个数
然后N行,每行4个整数,x,y,z,H
-100<=x,y,z<=100代表该星球的坐标,H代表改星球有没有AC燃料站,1代表有,0代表没有
然后是0<=C<=100,1<=S<=5意义见题目描述
然后是三个整数-100<=tx,ty,tz<=100代表DR星的位置
Output
对每组测试数据输出DR需要的最小时间,每组输出占一行,如果DDR不能会回到DR星则输出-1Sample Input
211 0 0 11 12 0 011 0 0 01 12 0 0Sample Output
2-1啊,不容易,在组长的提示下,在re和wa之间交错,我终于过了!
以电量来建边,以时间作为边权,这题的dis要用二维,第一维记录节点,第二维记录剩余次数;队列也要记录两个值:一为节点,二为剩余次数;之后找最小值的就可以了;
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const int maxn=1005;
const int Maxn=2*1002*1002;
const int INF=0x3f3f3f3f;
struct edge{
int v,w;
int next;
};
edge side[Maxn];
int head[maxn];
int N;
int top=0;
void addEdge(int from,int to,int w)
{
side[top].v=to;side[top].w=w;
side[top].next=head[from];
head[from]=top++;
}
int ac[maxn];
int x[maxn],y[maxn],z[maxn];
int inqueue[maxn];
int dis[maxn][10];
int C,S;
typedef pair<int ,int> Pair;
int spfa(int from ,int to)
{
memset(dis,INF,sizeof(dis));
memset(inqueue,0,sizeof(inqueue));
dis[from][S]=0;
inqueue[from]=1;
queue<Pair> que;
que.push(Pair(from,S));
while(!que.empty()){
int x=que.front().first,acx=que.front().second;
que.pop();
inqueue[x]=0;
if(acx==0)continue;
for(int i=head[x];i!=-1;i=side[i].next){
int y=side[i].v;
int acy;
if(ac[y]==1) acy=S;
else acy=acx-1;
if(dis[y][acy]>dis[x][acx]+side[i].w){
dis[y][acy]=dis[x][acx]+side[i].w;
if(!inqueue[y]&&acy!=0){
que.push(Pair(y,acy));
inqueue[y]=1;
}
}
}
}
/*for(int i=0;i<=N+1;i++){
for(int j=0;j<=S;j++)
printf("%d(%d):%d\n",i,j,dis[i][j]);
}*/
int MIN=INF;
for(int i=0;i<=S;i++){
MIN=min(MIN,dis[N+1][i]);
//printf("%d:%d\n",i,dis[N+1][i]);
}
return MIN;
}
int main()
{
//freopen ("int.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
memset(head,-1,sizeof(head));
x[0]=0;y[0]=0;z[0]=0;
for(int i=1;i<=N;i++){
scanf("%d%d%d%d",&x[i],&y[i],&z[i],&ac[i]);
}
scanf("%d%d",&C,&S);
scanf("%d%d%d",&x[N+1],&y[N+1],&z[N+1]);ac[N+1]=1;
top=0;
for(int i=0;i<=N+1;i++){
for(int j=1;j<=N+1;j++){
if(i!=j&&(abs(x[i]-x[j])+abs(y[i]-y[j])+abs(z[i]-z[j])<=C)){
int time=(max(abs(x[i]-x[j]),max(abs(y[i]-y[j]),abs(z[i]-z[j])))+min(abs(x[i]-x[j]),min(abs(y[i]-y[j]),abs(z[i]-z[j])))+1)/2;
//printf("%d->%d:time:%d\n",i,j,time);
addEdge(i,j,time);
addEdge(j,i,time);
}
}
}
/* for(int i=0;i<maxn;i++){
if(head[i]!=-1){
for(int x=head[i];x!=-1;x=side[x].next){
int y=side[x].v,len=side[x].w;
printf("%d->%d:%d\n",i,y,len);
}
}
}*/
int ans=spfa(0,N+1);
if(ans==INF)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- CSU1307 并查集+SPFA
- USACO/butter 3.2.6
- hdu 1596 find the safest road(spfa算法)
- [网络流24题 #18]分配问题
- [网络流24题 #18]分配问题
- Bellman-ford算法学习与SPFA算法
- 可以处理负权的单源最短路径的SPFA算法带图详解(自己画的图)
- XYZZY UVA10557
- HDU 1535 Invitation Cards
- HDU 2066 一个人的旅行
- Spfa模板
- hdu 4571 Travel in time
- hdu 4784 Dinner Coming Soon
- HDOJ 4396 —— 二维SPFA
- poj 1860 Currency Exchange
- 图论最短路之spfa
- POJ 1511 Invitation Cards
- POJ 3159 Candies
- bellman-ford的一般形式(下一站:spfa)
- 我的spfa (= =)!