Problem Description
There are n Doge Planets in the Doge Space. The conqueror of Doge Space is Super Doge, who is going to inspect his Doge Army on all Doge Planets. The inspection starts from Doge Planet 1 where DOS (Doge Olympic Statue) was built. It takes Super Doge exactly Txy time to travel from Doge Planet x to Doge Planet y.
With the ambition of conquering other spaces, he would like to visit
all Doge Planets as soon as possible. More specifically, he would like
to visit the Doge Planet x at the time no later than Deadlinex.
He also wants the sum of all arrival time of each Doge Planet to be as
small as possible. You can assume it takes so little time to inspect his
Doge Army that we can ignore it.
Input
There are multiple test cases. Please process till EOF.
Each test case contains several lines. The first line of each test
case contains one integer: n, as mentioned above, the number of Doge
Planets. Then follow n lines, each contains n integers, where the y-th
integer in the x-th line is Txy . Then follows a single line containing n - 1 integers: Deadline2 to Deadlinen.
All numbers are guaranteed to be non-negative integers smaller than
or equal to one million. n is guaranteed to be no less than 3 and no
more than 30.
Output
If some Deadlines can not be fulfilled, please output “-1” (which
means the Super Doge will say “WOW! So Slow! Such delay! Much Anger! . .
. ” , but you do not need to output it), else output the minimum sum of
all arrival time to each Doge Planet.
Sample Input
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
Sample Output
36
-1
题目大意:n(n<31)个节点,编号为0~n-1。起点是0节点,每个节点只能经过一次并且要在限制内的时间到达,现在要把到达每个点的时刻都加起来,求满足条件的最小时刻和。
题目分析:DFS。思路不难,但要剪枝。总结一下,剪枝无非有两条依据,一是根据题目中(不易发现)的条件剪枝,二是根据预测出的答案来剪枝,即根据通过当前的阶段解预测出来的近似当前方案最优解的解与已知最优解的优劣,来决定是否剪去。落实到这道题上来应该这么剪:1.如果在当前方案下,到达某个未到达过的点时的时刻已经超出时间限制,则剪枝;2.根据当前已用时间time和未到达过的点数num来预测出一个尽可能接近当前方案最优解的一个解time+time*num,当这个解比已经得到的最优解ans大时,则剪去。
做后感:这是一道好题,值得一做。
代码如下:
# include<iostream> # include<cstdio> # include<cstring> # include<algorithm> using namespace std; # define LL long long const int INF=1<<30; int mp[35][35],n,a[35],ans,vis[35]; void floyd() { for(int k=0;k<n;++k) for(int i=0;i<n;++i) for(int j=0;j<n;++j) mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]); } void dfs(int cur,int time,int att,int num) { if(num==n){ ans=min(ans,att); return ; } if(att+(n-num)*time>=ans) return ; for(int i=1;i<n;++i) if(!vis[i]&&time+mp[cur][i]>a[i]) return ; for(int i=1;i<n;++i){ if(vis[i]) continue; vis[i]=1; dfs(i,time+mp[cur][i],att+time+mp[cur][i],num+1); vis[i]=0; } } int main() { while(~scanf("%d",&n))///在这里如果用“!=EOF”会超时。 { for(int i=0;i<n;++i) for(int j=0;j<n;++j) scanf("%d",&mp[i][j]); floyd(); a[0]=0; for(int i=1;i<n;++i) scanf("%d",a+i); memset(vis,0,sizeof(vis)); ans=INF; vis[0]=1; dfs(0,0,0,1); if(ans!=INF) printf("%d\n",ans); else printf("-1\n"); } return 0; }