题意:有n个城市m条路。从1出发回到1,要访问选定的几个城市,这几个城市可以打工,
但是打工需要用di买执照,打工可以挣ci。问能不能访问所有选定的城市并且拿到所有执照。
分析:
1、先用floyd预处理出任意两点之间的最短距离,然后dfs搜。
2、要注意的是判断重边,n<=100,m<=5000,很明显m>=2*n。
#include<cstdio> #include<cstring> #include<iostream> #define INF 10000000 using namespace std; int e[110][110]; bool vis[110]; int n,h,money,flag; struct choose { int id,c,d; }node[20]; int minn(int x,int y) { return x<y?x:y; } void init() { for(int i=0;i<=n;i++) { for(int j=0;j<=n;j++) { if(i==j) e[i][j]=0; else e[i][j]=INF; } } memset(vis,0,sizeof(vis)); flag=0; } bool dfs(int x,int cnt) { if(cnt==h) { if(money-e[x][1]>=0) return true; } for(int i=0;i<h;i++) { if(e[x][node[i].id]!=INF && money-e[x][node[i].id]>=node[i].d) { if(!vis[node[i].id]) { vis[node[i].id]=true; money=money-e[x][node[i].id]-node[i].d+node[i].c; if(dfs(node[i].id,cnt+1)) return true; vis[node[i].id]=false; money=money+e[x][node[i].id]+node[i].d-node[i].c; } } } return false; } int main() { int T,m,a,b,cc; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&money); init(); for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&cc); if(a!=b) { e[a][b]=minn(e[a][b],cc); e[b][a]=minn(e[b][a],cc); } } scanf("%d",&h); for(int i=0;i<h;i++) scanf("%d%d%d",&node[i].id,&node[i].c,&node[i].d); for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(e[i][k]+e[k][j]<e[i][j]) e[i][j]=e[i][k]+e[k][j]; } } } if(dfs(1,0)) puts("YES"); else puts("NO"); } return 0; }
hdu 4284 Travel (dfs+floyd预处理)
原文:http://blog.csdn.net/u012841845/article/details/18900203