题意:给N个点,还有另外m个点(当中仅仅能选K个)。求最短路。
思路:在SPFA的基础上,用一个数组来统计,在某点入队时(要拓展其它点了),若该点是m个点中的,则count【i】=原来的+1;若不是。则继承原来的。出队时候限制一下。若大于K了,就停止拓展。
原题:眼下在一个非常大的平面房间里有 n 个无线路由器,每一个无线路由器都
固定在某个点上。不论什么两个无线路由器仅仅要距离不超过 r 就能互相建立网
络连接。
除此以外。另有 m 个能够摆放无线路由器的位置。你能够在这些位置
中选择至多 k 个增设新的路由器。
你的目标是使得第 1 个路由器和第 2 个路由器之间的网络连接经过尽
量少的中转路由器。
请问在最优方案下中转路由器的最少个数是多少?
#include<iostream> #include<vector> #include<queue> using namespace std; struct points { int x,y; }; const int inf=0x3f3f3f3f; int n,m,k,r; vector<points>v; //点 int map[205][205]; //图 int dis(points a,points b) //距离 { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } void get_gra() //建图 { for(int i=0;i<n+m;i++) { for(int j=i+1;j<n+m;j++) { if(dis(v[i],v[j])<=r*r) { map[j][i]=map[i][j]=1; } else { map[i][j]=map[j][i]=inf; } } } } int inq[205]; int d[205]; int count[205]; void spfa() { queue<int>q; for(int i=0;i<n+m;i++) { count[i]=inq[i]=0; d[i]=inf; } q.push(0);inq[0]=1;d[0]=0; while(!q.empty()) { int cur=q.front(); q.pop();inq[cur]=0; if(count[cur]>k)continue; //限制。某点出队的次数 for(int i=0;i<n+m;i++) { if(d[i]>d[cur]+map[cur][i]) { d[i]=d[cur]+map[cur][i]; if(inq[i]==0) { if(i>=n) //被限制次数的点,若是经过该点(该点入队),则加 { count[i]=count[cur]+1; } else //一般的点继承 { count[i]=count[cur]; } inq[i]=1; q.push(i); } } } } } int main() { while(cin>>n>>m>>k>>r) { v.clear(); points temp; for(int i=0;i<n+m;i++) { cin>>temp.x>>temp.y; v.push_back(temp); } get_gra(); spfa(); cout<<d[1]-1<<endl; //问的是中间有几个点 } return 0; }