• 贪心的思路: 借助筛子的比喻,很快迎刃而解

  • 切换次数最少 ——> 本次切换选择的Vpn使用的时间尽量长

  • 根据访问序列,访问了和n-1个Vpn相同的serve(一直都不会切换)

  • 直到最后一个剩余的Vpn也和serve相同必须切换

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
string vpn[1001];
string serve[5001];
bool flag[1001];

int choose(int m,int n){//
    int k=n;//可用代理数量
    int sum=0;//切换次数
    memset(flag,0,sizeof(flag));
    for(int i=0;i<m;i++){//从头遍历访问服务器
        for(int j=0;j<n;j++){//比较当前服务器和代理是否相同
            if(serve[i]==vpn[j]&&flag[j]==false){//第一次相同
                flag[j]=true;//标记对应代理为不可用
                k--;
                break;
                }
            }
        
        if(k==0){//当前访问将导致无可用代理
            if(n==1)return -1;//只有一个代理则失败
            memset(flag,0,sizeof(flag));//重置可用代理数量及标记
            k=n;
            sum++;
            i--;//回退一次
         }
        }
    return sum;
}

int main(){
    int n,m;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++)cin>>vpn[i];
        scanf("%d",&m);
        for(int i=0;i<m;i++)cin>>serve[i];
        printf("%d\n",choose(m,n));
        
    }
    return 0;
}

ps:自己做的时候盯着前n-1个Vpn被访问了,切换的时间又单独考虑很麻烦

  • 关键抓住切换的时机,全都被标记了才切换,切换时可以回退一次,使状态和开始完全相同