您的位置:首页 > 产品设计 > UI/UE

HDU-4848 Wow! Such Conquering! (floyd+dfs+剪枝)

2018-04-02 22:58 507 查看
链接
大致意思给出各个星球到其他星球的距离,然后给出一个到其他星球的最晚时间。求到各个星球的时间的和。其实挺好理解的,但是最扎心的是下面给的hint是错  的!!!
我是真的看了半天题目以为理解了又被这个hint劝退了。
思路
Floyd出最短路径。然后开始dfs.我一开始以为8000ms随便写,然后还是会超时的。
剪枝。目前有的几种可以直接跳出循环思想。
1当前已耗费时间+去下一个星球的时间已经超过ddl了(遍历所以未访问的星球)
2当前时间已经超过了我们前面算出来过的一个时间
3访问完毕
其中最为关键的是第二点。因为我 之前是对于每一次加时间 sum=sum+lon(当前路径长度)+dis[x][i](当前点到下一个点的距离)超时 .而写总长度sum=sum+dis[x][i]*ge(会重复计算的次数)就ac
为什么?因为第二种相比第一种,因为直接把边的重复算了进去,而第一种是慢慢算进去的,也就是说,如果点足够多的话,第一种算法会对于本已经不需要算的dfs继续算下去。这太浪费时间了!以至于我可以从超时变成300+ms.
代码#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof a)
#define mal(a,b) a=(b*)malloc(sizeof(b))
#define st std::ios::sync_with_stdio(false);
using namespace std;
const int maxn=1e7+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
int dis[30+5][30+5];
int ddl[30+5];
int vis[30+5];
int ans;
int n;

void dfs(int x,int num,int lon,int ge,int all){
// cout<<"num="<<num<<" x="<<x<<" all="<<all<<endl;
if(num==n){
ans=min(all,ans);
return;
}
if(all>ans) return ;
for(int i=1;i<n;i++){
if(!vis[i]){

4000
if((lon+dis[x][i])>ddl[i]) return ;
}
}
for(int i=1;i<n;i++){
if(!vis[i]){
vis[i]=1;
dfs(i,num+1,lon+dis[x][i],ge-1,all+dis[x][i]*ge);
vis[i]=0;
}
}

}
int main(){
while(~scanf("%d",&n)){
mem(vis,0);
ans=1000000;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
scanf("%d",&dis[i][j]);
}
}
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(dis[i][j]>dis[i][k]+dis[k][j]){
dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
}
/* cout<<endl;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cout<<dis[i][j]<<" ";
}
cout<<endl;
}*/
for(int i=1;i<n;i++){
scanf("%d",&ddl[i]);
}
dfs(0,1,0,n-1,0);
if(ans!=1000000) printf("%d\n",ans);
else printf("-1\n");
}
}
摸鱼生活差不多该结束了~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: