hdu3832(2011 Multi-University Training Contest 1 - Host by HNU )

題意:給n個點,求將前三個點連接起來的使用的最少的點的個數(每個點都有半徑,兩個點相連接表示兩個的半徑和大於或等於兩點間的距離)。

思路:我沒有想出該怎麼做,想了很久,後來看了題解,題解用的是最短路做。開始我嘗試用最小生成樹做。但是不知道該怎麼弄。到最後只有用DFS我可能才能做出來。怕超時於是放棄了。其實最小生成樹也給了我很大的啓示。判斷點的聯通用最小生成樹,從這裏也可以看到我學算法不具有靈活性,不會轉換模型。後來用的是求最短路的方法。以三個點分別爲原點然後求其的最短路。然後找到一個點到三個點的最短的距離。得解。

上代碼:

#include<cstdio>
#include<math.h>
using namespace std;
struct node{
int x,y;
int r;
};
node a[210];
int g[210][210],value;
int dis(node x1,node x2){
if((x1.x-x2.x)*(x1.x-x2.x)+(x1.y-x2.y)*(x1.y-x2.y)<=(x1.r+x2.r)*(x1.r+x2.r))
return 1;
return 0;
}
int maxint=10000000;
int d[3][210],vis[210];
void spfa(int n,int s){
int queue[1001],i,h,r;
for(i=0;i<=n-1;i++){
d[s][i]=maxint;
vis[i]=0;
}
d[s][s]=0;
h=0;r=1;
queue[0]=s;
vis[s]=1;
while(h!=r){
int u=queue[h++];
vis[u]=0;
for(i=0;i<=n-1;i++){
if(d[s][i]>d[s][u]+g[u][i]){
d[s][i]=d[s][u]+g[u][i];
if(!vis[i]){
vis[i]=1;
queue[r++]=i;
}
}
}
}
}
main(){
int t;
int n,i,j,min;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=0;i<=n-1;i++){
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].r);
}
for(i=0;i<=n-1;i++){
for(j=0;j<=n-1;j++){
g[i][j]=10000000;
if(dis(a[i],a[j])){
g[i][j]=1;
}
}
}
for(i=0;i<=2;i++){
spfa(n,i);
}
min=10000000;
for(i=0;i<=n-1;i++){
if(min>d[0][i]+d[1][i]+d[2][i]){
min=d[0][i]+d[1][i]+d[2][i];
}

}
if(min+1>n)
printf("-1\n");
else{
printf("%d\n",n-min-1);
}
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章