算法题之好友推荐

时间:2023-01-21 21:56:11

 

题目要求:

有n个人,每个人都有各自的好友列表。给定一个阈值p,当A和B的共同好友数超过p则推荐A和B为好友。请实现自动推荐直到没有好友可以推荐(每次推荐默认同意,即一定成为好友),然后进行一些查询。

查询1:A的好友数有几个?如果A不在这n个里面,输出-1,否则输出好友数;

查询2:A和B是好友吗?如果是则输出0,否则输出-1。

输入:p n m x y

p为阈值,n为人数,m为初始时的好友,x为查询1的个数,y为查询2的个数

注: - 如果A是B的好友,B一定是A的好友; - 每个人的人名用不超过20个字符的字符串表示,没有重名的人; - 人数不超过100.

输入示例:
2 3 3 3 3
A
B
C
A B
B C
A C
A
B
C
A B
C A
B C
应输出:
2
2
2
0
0
0

我的思路:

1.根据输入的好友数量N,建立一个N*N的关系矩阵,1表示为好友,0表示非好友关系。这样做的好处是便于保存和修改好友关系。注意点:每次修改时要对m,n和n,m两个位置的元素进行修改;对第i行遍历时从第i+列开始即可。

2.好友推荐处理过程就是对关系矩阵的处理,遍历矩阵每一行,当为非好友时,通过矩阵算出共同好友数;为好友时,跳过;当共同好友数超过阈值时将值设为1。直到关系矩阵不再被改变为止,此时已无可推荐好友了。

3.基于处理后的关系矩阵,根据输入的查询进行计算即可。

#include<string>
#include<iostream>
#include<vector>
#include<algorithm>//用到其中的find()函数,返回迭代器或指针
using namespace std;

int friendnum(vector<int> &R,vector<string> &namelist, string name,int N)
{
    int loc=find(namelist.begin(),namelist.end(),name)-namelist.begin();
    int count=0;
    if(loc>N-1)
        count=-1;
    else
    {
    for(int i=0;i<N;i++)
        if(R[loc*N+i]==1)
            count++;
    }
    return count;
}

int isfriend(vector<int> &R,vector<string> &namelist, string name1,string name2,int N)
{
    int loc1=find(namelist.begin(),namelist.end(),name1)-namelist.begin();
    int loc2=find(namelist.begin(),namelist.end(),name2)-namelist.begin();
    int count=-1;
    if(loc1>N-1||loc2>N-1)
        count=-1;
    else
    {
        if(R[loc1*N+loc2]==1)
            count=0;
    }
    return count;
}

void main()
{
    while(1)
    {
        vector<string> namelist;
        string nametemp;
        int P,N,M,X,Y;
        cin.clear();
        cin.sync();
        cin>>P>>N>>M>>X>>Y;
        vector<int> R(N*N,0);//建立关系矩阵,默认为0,非好友
        int n=N;//人数
        while(n--)//建立姓名列表
        {
            cin>>nametemp;
            namelist.push_back(nametemp);
        }
        int m=M;
        string name1,name2;
        int name1_it,name2_it;
        while(m--)//填充关系矩阵
        {
            cin>>name1>>name2;
            name1_it=find(namelist.begin(),namelist.end(),name1)-namelist.begin();//注意string.find()返回的是下标,而find()返回的是迭代器,用find()函数在容器中获得下标方法find(vec_aa.begin(),vec_aa.end(),2)-vec_aa.begin();没有找到时返回值超过边界。
            name2_it=find(namelist.begin(),namelist.end(),name2)-namelist.begin();//似乎string不需要用到迭代器,可返回下标,也可使用下标。string.back()是什么鬼?
            R[name1_it*N+name2_it]=1;
            R[name2_it*N+name1_it]=1;
        }
        //显示初始好友关系矩阵。1:好友;2:非好友
        //for(int i=0;i<N;i++)
        //{
        //    for(int j=0;j<N;j++)
        //        cout<<R[N*i+j]<<' ';
        //    cout<<endl;
        //}

        //好友推荐过程
        int flag=1;
        while(flag)
        {
            flag=0;//用于判断是否结束推荐
            for(int i=0;i<N;i++)
            {
                for(int j=i+1;j<N;j++)
                {
                    if(R[N*i+j]!=1)//不是好友
                    {//判断是否符合推荐阈值
                        int count=0;
                        for(int k=0;k<N;k++)
                            if(R[N*i+k]==R[N*j+k])//k为其共同好友
                                count++;
                        if(count>=P)//达到阈值
                        {
                            R[N*i+j]=1;//成为相互间的好友
                            R[N*j+i]=1;//修改关系矩阵
                        }
                        flag=1;//有推荐改动,继续推荐循环
                    }
                }
            }
        }
        //显示好友推荐完成后的好友关系矩阵。1:好友;2:非好友
        //for(int i=0;i<N;i++)
        //{
        //    for(int j=0;j<N;j++)
        //        cout<<R[N*i+j]<<' ';
        //    cout<<endl;
        //}
        //cout<<"x y="<<X<<' '<<Y<<endl;

        //推荐结束,响应查询
        vector<int> qury1; //查询1答案记录
        int x=X;
        int y=Y;
        while(x--)
        {
            string tempqury;
            cin>>tempqury;
            int tempans=friendnum(R, namelist, tempqury, N);
            qury1.push_back(tempans);
        }

        vector<int> qury2; //查询2记录
        while(y--)
        {
            string name1;
            string name2;
            cin.sync();
            cin.clear();
            cin>>name1>>name2;
            int tempans=isfriend(R, namelist, name1, name2, N);
            qury2.push_back(tempans);
        }
        //输出结果
        for(int i=0;i<X;i++)
            cout<<qury1[i]<<endl;
        for(int i=0;i<Y;i++)
            cout<<qury2[i]<<endl;

    }

    //int aa[]={1,2,3,4};
    //vector<int> vec_aa(aa,aa+4);
    ////string a=str(str.find("a"));
    ////string::iterator it=str.find("a");
    ////vector<int>::iterator loc=find(vec_aa.begin(),vec_aa.end(),2)-vec_aa.begin();
    //int loc=find(vec_aa.begin(),vec_aa.end(),2)-vec_aa.begin();
    //cout<<vec_aa[loc];

}
//测试集
//输入:
//2 3 3 3 3 
//A 
//B 
//C 
//A B 
//B C 
//A C 
//A 
//B 
//C 
//A B 
//C A 
//B C

//应输出: 
//2 
//2 
//2 
//0 
//0 
//0


1.find()和string.find()区别:algorithm库中的find()返回的是迭代器,输入三个参数,开始和结束的迭代器,待寻找值。获得下标值得方式是find(.begin(),.end(),xx)-.begin();string.find()返回的是下标值。