4 0 3 8 6 4 0 7 4 7 5 0 2 6 9 3 0 30 8 30 4 0 2 3 3 2 0 3 3 2 3 0 3 2 3 3 0 2 3 3
36 -1题意:n个点,要求从1点开始跑,遍历所有点,要求到达每个点的时间<=time[i],求到达每个点时间的总和最小。爆搜+最优性剪枝+可行性剪枝(参考别人的)#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cctype> #include <cmath> #include <cstdlib> #include <vector> #include <queue> #include <set> #include <map> #include <list> #define L long long using namespace std; const int INF=0x3f3f3f3f; const int maxn=32; int dis[maxn][maxn]; int n,tim[maxn]; void Floyd() { for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); } int vis[maxn],ans; void dfs(int src,int cur_time,int sum_time,int num) { if(num==n) { ans=min(ans,sum_time); return ; } //最优性剪枝:当前总时间+当前时间*剩余点数(因为往后到达的点的时间总是小于等于当前时间的)>=当前最优解 剪掉 if(sum_time+cur_time*(n-num)>=ans)return ; //可行性剪枝:如果当前时间有超Deadtime的,剪掉 for(int i=2;i<=n;i++) if(!vis[i]&&cur_time>tim[i]) return ; for(int i=2;i<=n;i++) { if(src!=i&&!vis[i]&&cur_time+dis[src][i]<=tim[i]) { vis[i]=1; dfs(i,cur_time+dis[src][i],sum_time+cur_time+dis[src][i],num+1); vis[i]=0; } } } int main() { while(~scanf("%d",&n)) { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&dis[i][j]); tim[1]=INF; for(int i=2;i<=n;i++) scanf("%d",&tim[i]); Floyd(); vis[1]=1; ans=INF; dfs(1,0,0,1); if(ans==INF)ans=-1; printf("%d\n",ans); } return 0; }
HDU 4848-Wow! Such Conquering!(DFS+最优性剪枝)
原文地址:http://blog.csdn.net/qq_16255321/article/details/40181917