【洛谷】P1690 贪婪的Copy(floyd+暴力路径,简单拿捏)

1:思路分析

:写图论题已经习惯先看一眼题解,基本可以筛选出或者排除一些算法

嗯....滑啊滑...n<=100.en....(cos:floyd吧,那又可以水过啦),看了一遍题意,确实floyd最短路+枚举路径顺序,拿捏!~

2:注意事项:

拿上我们全排列好bro,登登,闪亮登场:nenxt_permutaion(a+1,a+1+n);

注意!sort(a+1,a+1+n);//************使用next_permumation,前要先排序!!
    //不然wa哭你,就因为这个我wa了好几发! 

因为(why):nenxt_permutaion(a+1,a+1+n)是从当前形态开始算,下一个是当前形态的最小变化的更大排列!!!!

3:两个路径遍历方式(next_permutation  vs    dfs)dfs快一些

next_permutation:

 sort(b+1,b+1+p);//************使用next_permumation,前要先排序!!
	//不然wa哭你,就因为这个我wa了好几发! 
	b[0]=1,b[p+1]=n;//起点,终点 
	do{//暴力全排列所有路径可以 
		int sum=0;
		for(int i=0;i<p+1;i++){
			sum+=mp[b[i]][b[i+1]];
		}
		mmin=min(mmin,sum);
	}while(next_permutation(b+1,b+1+p));//全排列,即暴力全最小值 

dfs:

dfs(1,p,0);//暴力枚举 路径 


void dfs(int now,int m,int sum){
	if(m==0){
		ans=min(ans,sum+mp[now][n]);
	}
	else{
		for(int i=1;i<=p;i++){
			if(!vis[i]){
				vis[i]=true;
				dfs(b[i],m-1,sum+mp[now][b[i]]);
				vis[i]=false;
			}
		}
	}
}

 

---------------------------------------------------------------------------------------------------------------------------------

4:okk上ACcode:

#include<bits/stdc++.h>
using namespace  std;
#define int long long 
#define inf 0x3f3f3f3f
const int N=1e2+10;
int mp[N][N],b[15],n,p,x;
void floyd(){
	for(int k=1;k<=n;k++)
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++){
		mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
	}
}
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++){//建图 
		for(int j=1;j<=n;j++){
			cin>>mp[i][j];
		}
	}
	
	floyd();//Floyd 
	
	cin>>p;
	
	int mmin=inf;
	for(int i=1;i<=p;i++) cin>>b[i];
   sort(b+1,b+1+p);//************使用next_permumation,前要先排序!!
	//不然wa哭你,就因为这个我wa了好几发! 
	b[0]=1,b[p+1]=n;//起点,终点 
	do{//暴力全排列所有路径可以 
		int sum=0;
		for(int i=0;i<p+1;i++){
			sum+=mp[b[i]][b[i+1]];
		}
		mmin=min(mmin,sum);
	}while(next_permutation(b+1,b+1+p));//全排列,即暴力全最小值 
	cout<<mmin<<"\n";
}
signed main(){
	
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int tt=1;
	//cin>>tt;
	while(tt--){
		solve();
	}
	return 0;
}

2:路径遍历二之--dfs要比全排列快!

#include<bits/stdc++.h>
using namespace  std;
#define int long long 
#define inf 0x3f3f3f3f
const int N=1e2+10;
int mp[N][N],b[15],n,p,ans=0x7ffffff;
bool vis[15];
void dfs(int now,int m,int sum){
	if(m==0){
		ans=min(ans,sum+mp[now][n]);
	}
	else{
		for(int i=1;i<=p;i++){
			if(!vis[i]){
				vis[i]=true;
				dfs(b[i],m-1,sum+mp[now][b[i]]);
				vis[i]=false;
			}
		}
	}
}
void floyd(){
	for(int k=1;k<=n;k++)
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++){
		mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
	}
}
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++){//建图 
		for(int j=1;j<=n;j++){
			cin>>mp[i][j];
		}
	}
	cin>>p;
	for(int i=1;i<=p;i++) cin>>b[i];
	floyd();//Floyd 
	dfs(1,p,0);//暴力枚举 路径 
	cout<<ans<<"\n";
}
signed main(){
	
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int tt=1;
	//cin>>tt;
	while(tt--){
		solve();
	}
	return 0;
}

over~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值