码迷,mamicode.com
首页 > 其他好文 > 详细

【ACM】CCF-201403-4 无线网络 图论的应用

时间:2015-09-15 21:57:11      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:

刷CCF中。。。

问题描述
  目前在一个很大的平面房间里有 n 个无线路由器,每个无线路由器都固定在某个点上。任何两个无线路由器只要距离不超过 r 就能互相建立网络连接。
  除此以外,另有 m 个可以摆放无线路由器的位置。你可以在这些位置中选择至多 k 个增设新的路由器。
  你的目标是使得第 1 个路由器和第 2 个路由器之间的网络连接经过尽量少的中转路由器。请问在最优方案下中转路由器的最少个数是多少?
输入格式
  第一行包含四个正整数 n,m,k,r。(2 ≤ n ≤ 100,1 ≤ k ≤ m ≤ 100, 1 ≤ r ≤ 108)。
  接下来 n 行,每行包含两个整数 xi 和 yi,表示一个已经放置好的无线 路由器在 (xi, yi) 点处。输入数据保证第 1 和第 2 个路由器在仅有这 n 个路由器的情况下已经可以互相连接(经过一系列的中转路由器)。
  接下来 m 行,每行包含两个整数 xi 和 yi,表示 (xi, yi) 点处可以增设 一个路由器。
  输入中所有的坐标的绝对值不超过 108,保证输入中的坐标各不相同。
输出格式
  输出只有一个数,即在指定的位置中增设 k 个路由器后,从第 1 个路 由器到第 2 个路由器最少经过的中转路由器的个数。
样例输入
  5 3 1 3
  0 0
  5 5
  0 3
  0 5
  3 5
  3 3
  4 4
  3 0
样例输出
  2

 

思路分析:这题如果能想到的话,对最短路径搜索的过程中添加不能走的限制条件(cnt[i][k]+cnt[k][j]<kk)即可。这里cnt是指i到j经过的可添加的点的个数,edge则是边,根据floyd算法进行小的改变即可。不过做这道题想起来还有点不容易(对我而言吧。。。)

 

#include <stdio.h>
#include <string.h>
#define LOCAL
typedef long long LL;
struct point {
    int x,y;
};
int n,m,kk,r;
int edge[205][205];//count from 1
point p[205];
int cnt[205][205];
void print() {
    printf("edge:\n");
    for(int i=1; i<=n+m; i++) {
        for(int j=1; j<=n+m; j++) {
            printf("%d ",edge[i][j]);
        }
        printf("\n");
    }
    printf("cnt:\n");
    for(int i=1; i<=n+m; i++) {
        for(int j=1; j<=n+m; j++) {
            printf("%d ",cnt[i][j]);
        }
        printf("\n");
    }
}
int main() {
#ifdef LOCAL
    freopen("data.in","r",stdin);
//    freopen("data.out","w+",stdout);
#endif
    while(scanf("%d%d%d%d",&n,&m,&kk,&r)!=EOF) {//编号大于n的是可添加路由器
        memset(edge,-1,sizeof(edge));
        memset(cnt,0,sizeof(cnt));
        for(int i=0; i<n+m; i++) {
            scanf("%d%d",&p[i].x,&p[i].y);
        }
        for(int i=0; i<n+m-1; i++) {
            for(int j=i+1; j<n+m; j++) {
                if(LL(p[i].x-p[j].x)*(p[i].x-p[j].x)+LL(p[i].y-p[j].y)*(p[i].y-p[j].y)<=LL(r)*r)
                    edge[i+1][j+1]=edge[j+1][i+1]=1;
            }
        }
        for(int i=1; i<=n+m; i++) edge[i][i]=0;
        for(int i=n+1; i<=n+m; i++) cnt[i][i]=1;
        for(int k=1; k<=n+m; k++) {
            for(int i=1; i<=n+m; i++) {
                for(int j=1; j<=n+m; j++) {
                    //printf("k:%d i:%d j:%d\n",k,i,j);
                    if(edge[i][k]==-1||edge[k][j]==-1) {
                        continue;
                    }
                    if(edge[i][j]==-1||edge[i][k]+edge[k][j]<edge[i][j]) {
                        if(k>n) {
                            if(cnt[i][k]+cnt[k][j]-1<=kk) {
                                edge[i][j]=edge[i][k]+edge[k][j];
                                cnt[i][j]=cnt[i][k]+cnt[k][j]-1;
                            }
                        } else {
                            if(cnt[i][k]+cnt[k][j]<=kk) {
                                edge[i][j]=edge[i][k]+edge[k][j];
                                cnt[i][j]=cnt[i][k]+cnt[k][j];
                            }

                        }
                    }
                }
            }
        }
        printf("%d\n",edge[1][2]-1);
    }
    return 0;
}

 

【ACM】CCF-201403-4 无线网络 图论的应用

标签:

原文地址:http://www.cnblogs.com/windcarp/p/4811489.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!