清华上机 代理服务器(贪心,区间覆盖,模板)

题目描述

    使用代理服务器能够在一定程度上隐藏客户端信息,从而保护用户在互联网上的隐私。我们知道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

思路1:一个代理服务器就是把访问代理服务器这个序列分为子区间,然后看看使用这些区间如何拼凑成整个。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
#define MAX 10005
string ds[1010],ys[5005];
// 区间数据结构
struct Region {
    // 左区间
    int left;
    // 右区间
    int right;
} p[MAX],interval,target;

bool comp(Region x,Region y)//多看两遍
{
    return (x.left<y.left);
}

// 贪心法// 区间覆盖问题
int region(Region time[], int n, Region target) {

    int begin=target.left,end=target.right;

    sort(time,time+n,comp);//区间按照a从小到大排序
    int count=0;
    int len=0,maxlen,tmp;
    int newbegin=begin;
    int i=0,j;
    while(len<end-begin)
    {
        maxlen=0;
        for(i; i<n; i++) //找当前begin情况下最长
        {
            if(time[i].left<=newbegin)
            {
                tmp=time[i].right-newbegin;
                if(tmp>maxlen)
                {
                    maxlen=tmp;
                    j=i;
                }
            }
            else
                break;
        }

        if(maxlen==0)//说明断了,不存在连续覆盖
        {
            //cout<<"no exit;";
            cout<<-1<<endl;
            return -1;
        }

        //cout<<"("<<time[j].left<<","<<time[j].right<<")"<<"  ";
        len+=maxlen;
        count++;
        newbegin=time[j].right;

    }
    cout<<count-1<<endl;  //一般输出count,这里特殊
    return count;
}

int main() {
    int n,m,realm=0;
    int cnt=0;
    cin>>n;
    string ts;
    for(int i=0; i<n; i++)
    {
        cin>>ds[i];
    }
    cin>>m;
    for(int i=0; i<m; i++)
    {
        cin>>ys[i];
    }
    realm=m;
    for(int i=0; i<n; i++)
    {
        string ts=ds[i];
        int st=0;
        for(int j=0; j<realm; j++)
        {
            if(ys[j]==ts)
            {
                interval.left=st;
                interval.right=j;
                if(j-st>0)
                    p[cnt++]=interval;
                st=j+1;
                //cout<<interval.left<<" "<<interval.right<<endl;
            }

        }
        interval.left=st;
        interval.right=realm;
        if(realm-st>0)
            p[cnt++]=interval;
        //cout<<interval.left<<" "<<interval.right<<endl;
    }
    target.left=0;
    target.right=realm;
    region(p, realm, target);

}

如果考试,我估计无法做出这个题目,第一,访问服务器列表是可以重复的,这个没有考虑到,第二,分后区间设置问题,并不是右区间是j-1,而是j。第三,还是多考虑,下面的解法更简单。

#include<bits/stdc++.h>
using namespace std;

int main() {
    int n,m;
    while(cin >> n) {
        string agent[n];//代理服务器ip
        for(int i = 0; i < n; i++) cin >> agent[i];

        cin >> m;
        string server[m];//服务器ip
        for(int i = 0; i < m; i++) cin >> server[i];

        int rowserver = 0;  //查找的行数
        int count = 0, change = 0; //count:计算每一个代理服务器最多能访问的服务器个数    ;change:转换次数
        int max, j; //max用来记录每次能访问最多的服务器个数

        while(rowserver < m) { //循环结束条件是所有服务器都被访问完 或者 没有能用的代理服务器了
            max = 0;
            for(int i = 0; i < n; i++) {
                j = rowserver;
                count = 0;//对于每次转换都先把count置为0,再进行计算
                while(j < m && agent[i]!=server[j]) { //到最后一个服务器或遇到相同ip跳出循环
                    count++;
                    j++;
                }
                if(count > max) max = count;
            }
            if(max==0) break;
            rowserver += max;
            change++;
        }
        if(max==0) cout << "-1";
        else cout << change-1 << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qiang_____0712/article/details/85107997
今日推荐