2596 售货员的难题
生活随笔
收集整理的這篇文章主要介紹了
2596 售货员的难题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2596 售貨員的難題
?
?時間限制: 1 s ?空間限制: 32000 KB ?題目等級 : 鉆石 Diamond 題解 題目描述?Description某鄉有n個村莊(1<n<=15),有一個售貨員,他要到各個村莊去售貨,各村莊之間的路程s(0<s<1000)是已知的,且A村到B村與B村到A村的路大多不同。為了提高效率,他從商店出發到每個村莊一次,然后返回商店所在的村,假設商店所在的村莊為1,他不知道選擇什么樣的路線才能使所走的路程最短。請你幫他選擇一條最短的路。
輸入描述?Input Description村莊數n和各村之間的路程(均是整數)
輸出描述?Output Description最短的路程
樣例輸入?Sample Input3
0 2 1
1 0 2
2 1 0
樣例輸出?Sample Output3
數據范圍及提示?Data Size & Hint本題可用最短路思想、搜索來解決,但是可能無法通過一組極限數據(且效率較低)。建議按樹狀DP考慮!
分類標簽?Tags?點此展開?
動態規劃?最小生成樹?圖論 AC代碼1: /*不會什么樹形DP,我做的是spfa(其實floyed就可以)+深搜+剪枝首先將邊反向,spfa處理所有點到1的距離,以備剪枝使用然后深搜得到答案剪枝:利用spfa得到的距離,當當前的dis+(n-t)*minn+f[x]>ans時,剪枝(minn是矩陣中的最短距離,n-t是還有幾步可以遍歷完所有的村莊) */ #include<cstring> #include<cstdio> #include<iostream> #include<queue> #define M 20 #define INF 3000000 using namespace std; int map[M][M],f[M],n,ans=INF,min1=INF; int a2[M][M]; bool vis[M]; queue<int> q; int read() {char c=getchar();int num=0,flag=1;while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}return num*flag; } void dfs(int x,int t,int dis) {if(dis>ans)return;if(dis+(n-t)*min1+f[x]>ans)return;if(t==n){ans=min(ans,dis+map[x][1]);return;}for(int i=1;i<=n;i++)if(!vis[i]){vis[i]=true;dfs(i,t+1,dis+map[x][i]);vis[i]=false;} } void spfa() {q.push(1);vis[1]=1;f[1]=0;while(!q.empty()){int x=q.front();q.pop();vis[x]=0;for(int i=1;i<=n;i++)if(a2[x][i]&&f[x]+a2[x][i]<f[i]){f[i]=f[x]+a2[x][i];if(!vis[i]){vis[i]=1;q.push(i);}}} } int main() {memset(f,0x3f3f3f3f,sizeof(f));n=read();for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){map[i][j]=read();a2[j][i]=map[i][j];min1=min(min1,map[i][j]);}spfa();memset(vis,0,sizeof(vis));vis[1]=1;dfs(1,1,0);printf("%d",ans);return 0; }AC代碼2:
#include<cstdio> #include<cstring> using namespace std; #define N 51 int n,tr[N][N],m=0x7fffffff; bool vis[N]; void run(int p,int d,int s){ int r; if(d==n){if(s+tr[p][1]<m) m=s+tr[p][1];return; } for(r=1;r<=n;r++){ if(!vis[r]&&tr[p][r]>0){ if(s+tr[p][r]>=m) break; vis[r]=1;run(r,d+1,s+tr[p][r]); vis[r]=0;} } } int main(){scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&tr[i][j]);vis[1]=1;run(1,1,0);printf("%d",m);return 0; }AC代碼3:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int f[20],map[16*16][16*16]; int n,a,b,c,sum=0x7f7f7f7f; void Dfs(int s ,int dis,int k) {f[s]=1;if((dis+(n-k))>=sum) return;if(k==n) {sum=min(sum,dis+map[s][1]);}for(int i=1;i<=n;i++){if(f[i]==0) {Dfs(i,dis+map[s][i],k+1);f[i]=0;}} } int main() {cin>>n;memset(f,0,sizeof f ); for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&map[i][j]);Dfs(1,0,1); printf("%d",sum); return 0; }?
轉載于:https://www.cnblogs.com/shenben/p/5758893.html
總結
以上是生活随笔為你收集整理的2596 售货员的难题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Elixir Ecto: 范围数据类型
- 下一篇: 【 Tomcat 】tomcat8.0