https://www.luogu.com.cn/problem/P1078
搜索,图论,剪枝,最短路
绿色题
思路一:搜索 1.输入,建边,用一个数组存储已经学习的文化, 2.搜索,以当前的点now去看能走到哪些边,然后对连上的点判断是否学过要去的点的文化,或要去的点排斥自己已经学过的文化的任意一种 3.剪枝方法一: 如果当前长度>=ans ,就直接return (这样还是会TLE掉一个点(92分))
4.剪枝方法二: 可以直接开一个数组存储从起点到图任意一点的最短路程,如果当前路程大于到当前点的最短路程就直接return (这样做可以拿满分)
#include<bits/stdc++.h> using namespace std; const int maxn=105; int n,k,m,s,t,c[maxn],a[maxn][maxn],tot,cnt,whk[maxn],ans=1e9,p[maxn][maxn],flag2=0,ssum[maxn]; bool flag; /*struct edge{ int dis,to,next; }e[maxn]; void add(int u,int v,int w) { tot++; e[tot].next=head[u]; e[tot].to=v; head[u]=tot; }*/ void dfs(int now,int sum) { if(sum>=ssum[now]) { return; } ssum[now]=sum; if(now==t) { flag2=1; return; } for(int i=1; i<=n; i++) { if(p[now][i]>0) { flag=1; for(int j=1; j<=cnt; j++) { if(a[c[i]][whk[j]]==1) { flag=0; break; } } if(flag==1) { whk[++cnt]=c[i]; dfs(i,sum+p[now][i]); cnt--; } } } return; } int main() { cin>>n>>k>>m>>s>>t; for(int i=1; i<=n; i++) ssum[i]=1e9; for(int i=1; i<=n; i++) { cin>>c[i]; } for(int i=1; i<=k; i++) { for(int j=1; j<=k; j++) { cin>>a[i][j]; } a[i][i]=1; } for(int i=1; i<=m; i++) { int u,v,d; cin>>u>>v>>d; if(p[u][v]==0||d<p[u][v]) p[u][v]=d; p[v][u]=d; } cnt=1; whk[cnt]=c[s]; dfs(s,0); if(flag2==1) cout<<ssum[t]<<endl; else{ cout<<-1<<endl; } return 0; }
标签:剪枝,return,NOIP2012,之旅,int,tot,maxn,P1078,now From: https://www.cnblogs.com/2elaina/p/16721127.html