Temukan Kombinasi elemen tengah dalam vektor

Saya memiliki vektor vector<Points>list_of_points; yang berisi titik A B C D A. Saya ingin mencari semua kemungkinan kombinasi vektor yang menjaga dua elemen terluar di tempat yang sama. Misalnya, A B C D A -- A B D C A -- A C B D A -- A C D B A -- A D B C A -- A D C B A. Ada saran bagaimana saya bisa melakukan ini?

Saya melakukan ini karena setiap titik memiliki koordinat x,y. Saya mencoba mencari jarak terpendek untuk pergi ke semua elemen dan kembali ke elemen aslinya. Saya berpikir untuk menetapkan jarak minimum sama dengan kombinasi pertama A B C D A, dan membandingkan semua kombinasi lainnya

//pseudocode
min distance = distance of A B C D A

while(there are still combinations){
   find another combinations of the vector.
   if that distance is smaller than min distance, make it the new min distance 
   save the path in a vector
}

Jika diperlukan, inilah implementasi saya

#include <cmath>
#include <string>
#include <vector>
#include <iostream>

using namespace std;

class Point
{
  private:
    int m_x;
    int m_y;
    string m_name;

  public:
    Point(int x, int y, string name)
      : m_x(x), m_y(y), m_name(name)
    {}
    
    Point(){};
    
    int getX() const {return m_x;}
    void setX(int x) {m_x=x;}

    int getY() const {return m_y;}
    void setY(int y) {m_y=y;}

    string getName() const {return m_name;}
    
    
    float getDistance(Point &other);

    string toString() const;

    void printPoint() const;

    // used for printing Point using << operator. For example:
    // Point p(1,2,"A");
    // cout << p << endl;
    friend ostream& operator<<(ostream &os, const Point &p);

};

class ListOfPoints
{ 
  private:
    int elements;
    
  public:
    vector<Point>sorted_list;
    vector<Point>unsorted_list;
    
    void Unsorted_add(Point &newPt);
    void Sorted_add(Point &newPt);
    void Create_unsorted();
    void Sort_list();
    
    void set_elements(int n);
    int get_elements();
    
    
    ListOfPoints();

    // adds a new point to the end of the list
    void addPoint(Point &newPt);
    
    // prints the list of points
    void printList() const;
    
    // draws the points
    void draw() const;

};

string Point::toString() const{
  // examples how to create string from small parts
  string str(m_name);
  str += " = (";
  str += std::to_string(m_x);
  str.append(",").append(std::to_string(m_y)).append(")");
  return str;
} 

float Point::getDistance(Point &other){
  float x1 = float(this->getX());
        cout << "this->x = "<< this->getX() <<endl;
        cout << "this->y = "<<this->getY() <<endl;
        float y1 = float(this->getY());
        float x2 = float(other.getX());
        float y2 = float(other.getY());
        //cout << "x = " << x2 << endl;
        //cout << "y = " << y2 << endl;
        float dist = sqrt( pow(x2-x1,2) + pow(y2-y1,2) );
        cout << "dist = " << dist << endl;
        return dist;
}
void Point::printPoint() const{
  cout << toString() << endl;
}

// used for printing Point using << operator.
// For example, the following code will work
// Point origin(0,0,'O');
// cout << origin;
ostream& operator<<(ostream &os, const Point &p) {
  return os << p.toString();
}

ListOfPoints::ListOfPoints() {

}


void ListOfPoints::Sorted_add(Point &newPt)  {
  sorted_list.push_back(newPt);
}

void ListOfPoints::Unsorted_add(Point &newPt)  {
  unsorted_list.push_back(newPt);
}


void ListOfPoints::set_elements(int n){
  elements = n;
}

int ListOfPoints::get_elements(){
  return this->elements;
}

void ListOfPoints::Create_unsorted(){
  int x;
  int y;
  string name;
  
  cout << "Enter the Number of elements" << endl;
  cin >> elements;
  for(int i = 0; i<elements; i++){
    cout << "Enter the name of the element: " << endl;
    cin >> name;
    cout <<"Enter the x value" << endl;
    cin >> x;
    cout <<"Enter they y vlaue" << endl;
    cin >> y;
    Point p(x,y,name);
    unsorted_list.push_back(p);
    
  }

  cout << elements << endl;
  return;
}

person CS_12319    schedule 06.12.2020    source sumber
comment
akan ada jumlah hasil nPn : di mana n adalah ukuran vektor - 2, dan nPn berarti permutasi. Anda mungkin harus menemukan cara untuk membatasinya, jika tidak, akan ada banyak hasil   -  person WARhead    schedule 06.12.2020
comment
Pustaka standar memiliki fungsi untuk menemukan permutasi yang disebut std::next_permutation. Anda cukup memberikan iterator ke elemen kedua dan terakhir sebagai rentang yang akan diubah dan kemudian secara manual menambahkan nilai pertama dan terakhir.   -  person nick    schedule 06.12.2020
comment
softwareengineering.stackexchange.com/questions/315836/ lihat ini untuk algoritma yang lebih baik, karena brute force mungkin tidak dapat dilakukan untuk vektor yang lebih panjang, brute force memiliki kompleksitas O(n!)   -  person WARhead    schedule 06.12.2020


Jawaban (1)


Berdasarkan uraian Anda, program berikut menunjukkan apa yang ingin Anda capai menggunakan std::next_permutation:

#include <algorithm>
#include <string>
#include <iostream>

int main()
{
    std::string test = "ABCDA";

    // sort the items after the beginning and before the end of the sequence
    std::sort(test.begin() + 1, std::prev(test.end()));
    do
    {
        std::cout << test << "\n";
      // permute the middle elements
    } while (std::next_permutation(test.begin() + 1, std::prev(test.end())));
}

Keluaran:

ABCDA
ABDCA
ACBDA
ACDBA
ADBCA
ADCBA

Untuk memperluas ini ke kelas Point Anda, Anda perlu mengurutkan titik tengah dengan cara tertentu, dan kemudian menerapkan logika yang sama menggunakan std::next_permutation.

Berikut ini contoh kecilnya:

#include <algorithm>
#include <vector>
#include <iostream>

struct Point
{
    int m_x;
    int m_y;
    int get_x() const { return m_x; }
    int get_y() const { return m_y; }
    Point(int x = 0, int y = 0) : m_x(x), m_y(y) {}
};
    
int main()
{
    std::vector<Point> test = {{0,0},{1,2},{2,1},{3,6},{2,7},{10,10}};
    std::vector<std::vector<Point>> results;
    auto sorter = [](const Point& p1, const Point& p2) { return std::tie(p1.m_x, p1.m_y) < std::tie(p2.m_x, p2.m_y); };
    
    // sort the items after the beginning and before the end of the sequence
    std::sort(test.begin() + 1, std::prev(test.end()), sorter);
    do
    {
        results.push_back(test);
    } while (std::next_permutation(test.begin() + 1, std::prev(test.end()), sorter));
    
    for (auto& r : results)
    {
        for (auto& p : r)
           std::cout << "{" << p.get_x() << "," << p.get_y() << ") ";
        std::cout << "\n";
    }
}

Keluaran:

{0,0) {1,2) {2,1) {2,7) {3,6) {10,10) 
{0,0) {1,2) {2,1) {3,6) {2,7) {10,10) 
{0,0) {1,2) {2,7) {2,1) {3,6) {10,10) 
{0,0) {1,2) {2,7) {3,6) {2,1) {10,10) 
{0,0) {1,2) {3,6) {2,1) {2,7) {10,10) 
{0,0) {1,2) {3,6) {2,7) {2,1) {10,10) 
{0,0) {2,1) {1,2) {2,7) {3,6) {10,10) 
{0,0) {2,1) {1,2) {3,6) {2,7) {10,10) 
{0,0) {2,1) {2,7) {1,2) {3,6) {10,10) 
{0,0) {2,1) {2,7) {3,6) {1,2) {10,10) 
{0,0) {2,1) {3,6) {1,2) {2,7) {10,10) 
{0,0) {2,1) {3,6) {2,7) {1,2) {10,10) 
{0,0) {2,7) {1,2) {2,1) {3,6) {10,10) 
{0,0) {2,7) {1,2) {3,6) {2,1) {10,10) 
{0,0) {2,7) {2,1) {1,2) {3,6) {10,10) 
{0,0) {2,7) {2,1) {3,6) {1,2) {10,10) 
{0,0) {2,7) {3,6) {1,2) {2,1) {10,10) 
{0,0) {2,7) {3,6) {2,1) {1,2) {10,10) 
{0,0) {3,6) {1,2) {2,1) {2,7) {10,10) 
{0,0) {3,6) {1,2) {2,7) {2,1) {10,10) 
{0,0) {3,6) {2,1) {1,2) {2,7) {10,10) 
{0,0) {3,6) {2,1) {2,7) {1,2) {10,10) 
{0,0) {3,6) {2,7) {1,2) {2,1) {10,10) 
{0,0) {3,6) {2,7) {2,1) {1,2) {10,10) 

Saya memilih kriteria pengurutan berdasarkan nilai x dan y, dengan nilai x dibandingkan terlebih dahulu

person PaulMcKenzie    schedule 06.12.2020
comment
Saya sedikit bingung apa yang dimaksud dengan sortir. Bagaimana saya tahu kriteria apa untuk mengurutkannya. Bukankah std::next_permuatation memerlukan semacam kriteria? Saya mencoba dan mendapatkan daftar kesalahan yang panjang. - person CS_12319; 06.12.2020
comment
Urutkan berdasarkan x lalu y. Lihat hasil editnya. - person PaulMcKenzie; 06.12.2020