【问题标题】:Optimization of transitive comparison (A>B, B>C => A>C)传递比较优化 (A>B, B>C => A>C)
【发布时间】:2015-04-06 03:24:32
【问题描述】:

我已经被这个问题困扰了将近一个星期,我想我需要一些帮助来解决它。我得到了一组这种格式的比较:

5
2
1 2
2 3
3 4
5 4
6 5

第一行表示有5个元素可以比较(1-5)
第二行表示会有多少比较语句
从第三行开始是比较语句。第一个元素优于第二个元素。所以在这种情况下 1 > 2 和 2 >3 和 3 > 4 等等。

我应该输出比每个元素更好和更差的元素数量。 所以没有数字比元素 1 好,也有 3 个数字比 1 差(2,3,4)。我想你应该已经明白了。输出应该是:

1:更好:0 更差:3
2:较好:1 较差:2
3:较好:2 较差:1
4:较好:5 较差:0
5:较好:1 较差:1
6:较好:0 较差:2

这是我到目前为止的实现

class Student{
public:
vector<int> better;
vector<int> worse;
};

void addComp(Student* student, int a, int b){

//push all worse elements into their better elements (there will be    duplicate)
student[a].worse.push_back(b);
vector<int>::iterator bIter = student[b].worse.begin();
vector<int>::iterator aIter = student[a].better.begin();

while (aIter != student[a].better.end())
{
    student[*aIter].worse.push_back(b);
    aIter++;
}

while (bIter != student[b].worse.end())
{
    student[a].worse.push_back(*bIter);

    aIter = student[a].better.begin();
    while (aIter != student[a].better.end())
    {
        student[*aIter].worse.push_back(*bIter);
        aIter++;
    }
    bIter++;
}

//push all better elements into their worse elements (there will be duplicate)
student[b].better.push_back(a);
bIter = student[b].worse.begin();
aIter = student[a].better.begin();

while (bIter != student[b].worse.end())
{
    student[*bIter].better.push_back(a);
    bIter++;
}

while (aIter != student[a].better.end())
{
    student[b].better.push_back(*aIter);

    bIter = student[b].worse.begin();
    while (bIter != student[b].worse.end())
    {
        student[*bIter].better.push_back(*aIter);
        bIter++;
    }
    aIter++;
 }
}

int main()
{
int studentCount, inputCount, testCase;
int a, b;
Student* student;

cin >> testCase;
while (testCase > 0)
{
    //The number of student that will be compared
    cin >> studentCount;

    student = new Student[studentCount + 1];

    //The number of comparison input
    cin >> inputCount;

    while (inputCount > 0)
    {
        cin >> a >> b;
        addComp(student, a, b);
        inputCount--;
    }

    //Start counting the number of better and worse student for each student
    for (int i = 1; i <= studentCount; i++)
    {
        //Remove duplicate from worse array
        sort(student[i].worse.begin(), student[i].worse.end());
        vector<int>::iterator last = std::unique(student[i].worse.begin(), student[i].worse.end());
        student[i].worse.erase(last, student[i].worse.end());

        //Remove duplicate from better array
        sort(student[i].better.begin(), student[i].better.end());
        vector<int>::iterator last2 = std::unique(student[i].better.begin(), student[i].better.end());
        student[i].better.erase(last2, student[i].better.end());

        cout << i " better: " << student[i].better.size() << " worse: " << student[i].worse.size() << endl;
    }
    delete [] student;
    testCase--;
 }
}

它工作得很好,但是对于这个问题它不够有效。待比较元素的数量最多可达到50个,比较语句的数量最多可达到10000条比较语句。这仅适用于一个测试用例。可以给出多个测试用例。如果您能指出一个更有效的算法或帮助优化我的代码,我将不胜感激。

【问题讨论】:

    标签: c++ performance optimization comparison logical-operators


    【解决方案1】:

    尝试消除 addComp 中的重复元素怎么样? 此外,您可以在 addComp 时对其进行排序。

    我建议您使用 set 而不是 vector,因为 set 可能是唯一的。 步骤 1. 用集合替换向量 步骤 2. 将 push_back 替换为 insert step 3. 去掉排序部分

    #include <set>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    class Student{
    public:
    set<int> better;
    set<int> worse;
    };
    
    void addComp(Student* student, int a, int b){
    
    //push all worse elements into their better elements (there will be    duplicate)
    student[a].worse.insert(b);
    set<int>::iterator bIter = student[b].worse.begin();
    set<int>::iterator aIter = student[a].better.begin();
    
    while (aIter != student[a].better.end())
    {
        student[*aIter].worse.insert(b);
        aIter++;
    }
    
    while (bIter != student[b].worse.end())
    {
        student[a].worse.insert(*bIter);
    
        aIter = student[a].better.begin();
        while (aIter != student[a].better.end())
        {
            student[*aIter].worse.insert(*bIter);
            aIter++;
        }
        bIter++;
    }
    
    //push all better elements into their worse elements (there will be duplicate)
    student[b].better.insert(a);
    bIter = student[b].worse.begin();
    aIter = student[a].better.begin();
    
    while (bIter != student[b].worse.end())
    {
        student[*bIter].better.insert(a);
        bIter++;
    }
    
    while (aIter != student[a].better.end())
    {
        student[b].better.insert(*aIter);
    
        bIter = student[b].worse.begin();
        while (bIter != student[b].worse.end())
        {
            student[*bIter].better.insert(*aIter);
            bIter++;
        }
        aIter++;
     }
    }
    
    int main()
    {
    int studentCount, inputCount, testCase;
    int a, b;
    Student* student;
    
    cin >> testCase;
    while (testCase > 0)
    {
        //The number of student that will be compared
        cin >> studentCount;
    
        student = new Student[studentCount + 1];
    
        //The number of comparison input
        cin >> inputCount;
    
        while (inputCount > 0)
        {
            cin >> a >> b;
            addComp(student, a, b);
            inputCount--;
        }
    
        //Start counting the number of better and worse student for each student
        for (int i = 1; i <= studentCount; i++)
        {
            cout << i << " better: " << student[i].better.size() << " worse: " << student[i].worse.size() << endl;
        }
        delete [] student;
        testCase--;
     }
    }
    

    【讨论】:

    • 感谢您的回答。我完全忘记了 std::set。但显然它仍然不够快。我在我的机器上对其进行了测试,它在 48 秒内运行了 1000 个测试用例。我应该把它弄到3以下。我想我必须从一个完全不同的角度来解决它。
    猜你喜欢
    • 2021-10-04
    • 2015-06-12
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多