1 条题解
-
0yao_yi LV 4 @ 2019-11-08 19:35:59
老师给的数据是过了的,我也是看的题解才会的
#include<iostream>// 用Dijkstra进行搜索
#include<cstdio>
#define M 1000000
//没必要让最大值为INT_MAX,比所有答案大就行,也方便运算
#define M2 210
//205,208,201,200 刚刚要超时 老师说是电脑问题
using namespace std;
int n,m,a,b,f[M2][M2],dp[M2][M2];//dp[a][b]表示状态(a,b),即1->a->b->1经历的最少点数,当然a可以等于b;而这里我指的是a->2->2->b的最少点数
bool v[M2][M2];//标记状态(a,b)是否被更新
int main()
{
//freopen("president.in","r",stdin);
//freopen("president.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)//定义距离数组
for(int j=0;j<n;j++)//没必要用memset()定义 ,老实写,踏实些
f[i][j]=(i==j?0:M);//这道题中ij相同指的是同一点,距离自然为零
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);//将数组整体向左上移动一下,方便理解计数,节约两排空间,目标状态就变成了dp[0][0]
f[--a][--b]=1;//有边距离定义为1,可理解为到得了这个点
}
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);//Floyd求任意两点距离
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dp[i][j]=M;//定义初始状态,为最大值
dp[1][1]=1;//定义初始状态(1,1)为1,平移前,实际上也就是(2,2);以它为初始状态保证了每一个状态由它更新,[当然走不到的点自然不行];
while(1)//死循环一枚,貌似f(;;)快一些 ||不断找出未使用过的最少状态,用其更新全部状态【用Dijkstra搜索目标状态】,上一行已经保证了全部更新的状态都经过2
{//题目暗含了必定有解,所以不会真的死循环
a=-1,b=-1;//初始的奇怪边
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(!v[i][j]&&(a==-1||dp[i][j]<dp[a][b])) a=i,b=j;//找目前未使用的最少状态
if(a==0&&b==0) break;//找到目标状态退出循环
v[a][b]=1;//标记
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i!=b&&i!=a&&j!=a&&j!=b)//更新时,不能与当前状态有重合
dp[i][j]=min(dp[i][j],dp[a][b]+f[b][i]+f[i][j]+f[j][a]-1);//状态转移,更新i->...->j的最少点,记得减去本身的1;重复的点随即被更新去掉【二维,Dijkstra,用最优状态更新、搜索】
}
printf("%d",dp[0][0]);
return 0;
}
- 1
信息
- 难度
- 10
- 分类
- (无)
- 标签
- (无)
- 递交数
- 1
- 已通过
- 0
- 通过率
- 0%
- 上传者