题型:搜索
题意:n个城市,从起点出发,经过在每个城市要求的deadline时间之前经过每一个城市,问最少需要的时间。
分析:
首先Floyd求出每个城市到其他各个城市的距离。然后DFS得出答案,DFS中需要加两个剪枝。
(1)如果到达一个城市的时间晚于相应的deadline,则不必往下搜索。
(2)如果搜索到最后的时间比当前已经搜出的最短时间答案还长,则不必往下搜索。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<algorithm>
#define M 35
#define inf 0x3f3f3f3f
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
int ans;
class Floyd {
int n,mat[M][M],i,j,k;
public:
void init(int x) {
n=x;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
mat[i][j]=i==j?0:inf;
}
void add(int u,int v,int w) {
mat[u][v]=w;
}
void solve() {
for(k=0; k<n; k++)
for(i=0; i<n; i++)
for(j=0; j<n; j++)
mat[i][j]=min(mat[i][j],mat[i][k]+mat[k][j]);
}
int getvalue(int x,int y) {
return mat[x][y];
}
} city;
int deadline[M];
int n;
bool vis[M];
void dfs(int start,int step,int now,int all) {
if(step==n-1) {
ans = min(ans,all);
return;
}
//剪枝
if(all + (n - step - 1) * now >= ans) return;
for(int i=1;i<n;i++){
if(!vis[i] && (now + city.getvalue(start,i) > deadline[i])){
return;
}
}
for(int i=1; i<n; i++) {
if(!vis[i]) {
vis[i] = true;
dfs(i,step+1,now+city.getvalue(start,i),all+now+city.getvalue(start,i));
vis[i] = false;
}
}
}
int main() {
while(~scanf("%d",&n)) {
city.init(n);
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
int w;
scanf("%d",&w);
city.add(i,j,w);
}
}
city.solve();
deadline[0] = inf;
for(int i=1; i<n; i++) {
scanf("%d",&deadline[i]);
}
ans = inf;
mt(vis,false);
dfs(0,0,0,0);
if(ans >= inf) {
puts("-1");
continue;
}
printf("%d\n",ans);
}
return 0;
}