代理服务器(清华考研机试题)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Fei20140908/article/details/82527754

题目描述

使用代理服务器能够在一定程度上隐藏客户端信息,从而保护用户在互联网上的隐私。我们知道n个代理服务器的IP地址,现在要用它们去访问m个服务器。这 m 个服务器的 IP 地址和访问顺序也已经给出。系统在同一时刻只能使用一个代理服务器,并要求不能用代理服务器去访问和它 IP地址相同的服务器(不然客户端信息很有可能就会被泄露)。在这样的条件下,找到一种使用代理服务器的方案,使得代理服务器切换的次数尽可能得少。
输入描述:
每个测试数据包括 n + m + 2 行。
第 1 行只包含一个整数 n,表示代理服务器的个数。
第 2行至第n + 1行每行是一个字符串,表示代理服务器的 IP地址。这n个 IP地址两两不相同。
第 n + 2 行只包含一个整数 m,表示要访问的服务器的个数。
第 n + 3 行至第 n + m + 2 行每行是一个字符串,表示要访问的服务器的 IP 地址,按照访问的顺序给出。
每个字符串都是合法的IP地址,形式为“xxx.yyy.zzz.www”,其中任何一部分均是0–255之间的整数。输入数据的任何一行都不包含空格字符。
其中,1<=n<=1000,1<=m<=5000。
输出描述:
可能有多组测试数据,对于每组输入数据, 输出数据只有一行,包含一个整数s,表示按照要求访问服务器的过程中切换代理服务器的最少次数。第一次使用的代理服务器不计入切换次数中。若没有符合要求的安排方式,则输出-1。
示例1
输入

3
166.111.4.100
162.105.131.113
202.112.128.69
6
72.14.235.104
166.111.4.100
207.46.19.190
202.112.128.69
162.105.131.113
118.214.226.52
输出

1

下面是代码和思路

# include <iostream>
# include <cstring>
# include <algorithm>
#include <cstdlib>
#include <map>
#define MAX 6000
using namespace std;
/**
* 思路是这样,有两个集合,第一个是n个代理服务器A,第二个是m个要访问的服务器B
* 利用贪心算法,这里为方便用数组下标代表每个ip,我用map来将每个代理服务器ip映射成整数
* 1.统计A中各IP在B中出现的最早位置,记录到cnt数组,如果没有出现过就采用默认值MAX(>m)
* 2.在cnt数组中寻找出现最晚的一个IP的位置,标记它的值为Index
* 3.一直访问到Index位置,才需要换服务器,换服务器次数+1,
* 接着从B的Index位置开始继续执行1,2步,直到Index的值大于m
* 4.特殊情况,n==1,此时如果B中出现了A中的Ip就一定行不通,否则才行得通
*/
struct Ip {
    int x, y, z, w;
    Ip(int a=0,int b=0, int c=0, int d=0):x(a),y(b),z(c),w(d){}
    bool operator < (const Ip & ip) const {
        if (x != ip.x)return x < ip.x;
        if (y != ip.y)return y < ip.y;
        if (z != ip.z) return z < ip.z;
        if (w != ip.w) return w < ip.w;
        return false;
    }
};
int n, m;
map<Ip, int>flect; // 用来将ip映射成数组下标
int cnt[1005]; // cnt[i]表示第i个ip在B中出现的位置
Ip dat[5005]; // dat数组存储B中的IP
void count(Ip * data, int start) { // 从start位置开始统计A中各ip在B中最早出现的位置
    for (int i = 0; i < n; i++) {// 初始化cnt
        cnt[i] = MAX;
    }
    for (int i = start; i < m; i++) {
        map<Ip, int>::iterator it = flect.find(data[i]);
        if (it!=flect.end()) {
            int index = it->second;
            if (cnt[index] > i) cnt[index] = i;
        }
    }
}
int findMax() {
    // 返回最晚出现的位置
    int max = 0;
    for (int i = 0; i < n; i++) {
        if (cnt[i] > max) {
            max = cnt[i];
        }
    }
    return max;
}
int main() {
    freopen("in.h", "r", stdin);
    while (cin >> n) {
        flect.clear(); // map清零
        for (int i = 0; i < n; i++) {
            Ip tmp;
            scanf("%d.%d.%d.%d", &tmp.x, &tmp.y, &tmp.z, &tmp.w);
            flect.insert(pair<Ip, int>(tmp, i));
        }
        cin >> m;
        for (int i = 0; i < m; i++) {
            scanf("%d.%d.%d.%d", &dat[i].x, &dat[i].y, &dat[i].z, &dat[i].w);
        }
        int flag = true;
        if (n == 1) { // n == 1时特殊情况特殊处理
            for (int i = 0; i < m; i++) {
                if (flect.find(dat[i]) != flect.end()) {
                    cout << -1 << endl;
                    flag = false;
                    break;
                }
            } 
            if (flag)cout << 0 << endl;
        }
        else{
            int res = -1; // 第一次不算,所以从-1开始累计
            int k = 0;
            while (k < m) {
                res++;
                count(dat, k);
                k = findMax();
            }
            cout << res << endl;
        }
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/Fei20140908/article/details/82527754