Dynamic Programming: Using tablulated space to avoid repeated recursive call.

Traveling Sales Man (TSP) problem Template: https://www.geeksforgeeks.org/bitmasking-dynamic-programming-set-2-tsp/

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

#define INF 99999999
#define MAXR 12
#define MAXC 12
#define MAXMASK 2048
#define MAXHOUSE 12

// stores distance taking souce
// as every dirty tile
int dist[MAXR][MAXC][MAXHOUSE];

// memoization for dp states
int dp[MAXHOUSE][MAXMASK];

// stores coordinates for
// dirty tiles
vector < pair < int, int > > dirty;

// Directions
int X[] = {-1, 0, 0, 1};
int Y[] = {0, 1, -1, 0};

char arr[21][21];

// len : number of dirty tiles + 1
// limit : 2 ^ len -1
// r, c : number of rows and columns
int len, limit, r, c;


// Returns true if current position
// is safe to visit
// else returns false
// Time Complexity : O(1)
bool safe(int x, int y)
{
    if (x >= r or y>= c or x<0 or y<0)
    return false;
    if (arr[x][y] == '#')
    return false;
    return true;
}


// runs BFS traversal at tile idx
// calulates distance to every cell
// in the grid
// Time Complexity : O(r*c)
void getDist(int idx){

    // visited array to track visited cells
    bool vis[21][21];
    memset(vis, false, sizeof(vis));

    // getting current positon
    int cx = dirty[idx].first;
    int cy = dirty[idx].second;

    // initializing queue for bfs
    queue < pair < int, int > > pq;
    pq.push({cx, cy});

    // initializing the dist to max
    // because some cells cannot be visited
    // by taking source cell as idx
    for (int i = 0;i<= r;i++)
        for (int j = 0;j<= c;j++)
            dist[i][j][idx] = INF;

    // base conditions
    vis[cx][cy] = true;
    dist[cx][cy][idx] = 0;

    while (! pq.empty())
    {
        auto x = pq.front();
        pq.pop();
        for (int i = 0;i<4;i++)
        {
        cx = x.first + X[i];
        cy = x.second + Y[i];
        if (safe(cx, cy))
        {
            if (vis[cx][cy])
                continue;
            vis[cx][cy] = true;
            dist[cx][cy][idx] = dist[x.first][x.second][idx] + 1;
            pq.push({cx, cy});
            }
        }
    }
}

// Dynamic Programming state transition recursion
// with memoization. Time Complexity: O(n*n*2 ^ n)
int solve(int idx, int mask)
{
    // goal state
    if (mask == limit)
    return dist[0][0][idx];

    // if already visited state
    if (dp[idx][mask] != -1)
    return dp[idx][mask];

    int ret = INT_MAX;

    // state transiton relation
    for (int i = 0;i<len;i++)
    {
        if ((mask & (1<<i)) == 0)
        {
            int newMask = mask | (1<<i);
            ret = min( ret, solve(i, newMask)
                + dist[dirty[i].first][dirty[i].second][idx]);
        }
    }

    // adding memoization and returning
    return dp[idx][mask] = ret;
}

void init()
{
    // initializing containers
    memset(dp, -1, sizeof(dp));
    dirty.clear();

    // populating dirty tile positions
    for (int i = 0;i<r;i++)
        for (int j = 0;j<c;j++)
        {
            if (arr[i][j] == '*')
            dirty.push_back({i, j});
        }

    // inserting ronot's location at the
    // begining of the dirty tile
    dirty.insert(dirty.begin(), {0, 0});

    len = dirty.size();

    // calculating LIMIT_MASK
    limit = (1<<len) - 1;

    // precalculating distances from all
    // dirty tiles to each cell in the grid
    for (int i = 0;i<len;i++)
    getDist(i);
}

int main(int argc, char const *argv[])
{
    // Test case #1:
    //     .....*.
    //     ...#...
    //     .*.#.*.
    //     .......

char A[4][7] = { {'.', '.', '.', '.', '.', '*', '.'},
                    {'.', '.', '.', '#', '.', '.', '.'},
                    {'.', '*', '.', '#', '.', '*', '.'},
                    {'.', '.', '.', '.', '.', '.', '.'}
                };

    r = 4; c = 7;

    cout << "The given grid : " << endl;

    for (int i = 0;i<r;i++)
    {
        for (int j = 0;j<c;j++)
        {
            cout << A[i][j] << " ";
            arr[i][j] = A[i][j];
        }
        cout << endl;
    }

    // - initializitiation
    // - precalculations
    init();

    int ans = solve(0, 1);

    cout << "Minimum distance for the given grid : ";
    cout << ans << endl;


    // Test Case #2
    //     ...#...
    //     ...#.*.
    //     ...#...
    //     .*.#.*.
    //     ...#...

    char Arr[5][7] = { {'.', '.', '.', '#', '.', '.', '.'},
                        {'.', '.', '.', '#', '.', '*', '.'},
                        {'.', '.', '.', '#', '.', '.', '.'},
                        {'.', '*', '.', '#', '.', '*', '.'},
                        {'.', '.', '.', '#', '.', '.', '.'}
                };#include <bits/stdc++.h>
using namespace std;

#define INF 99999999
#define MAXR 12
#define MAXC 12
#define MAXMASK 2048
#define MAXHOUSE 12

// stores distance taking souce
// as every dirty tile
int dist[MAXR][MAXC][MAXHOUSE];

// memoization for dp states
int dp[MAXHOUSE][MAXMASK];

// stores coordinates for
// dirty tiles
vector < pair < int, int > > dirty;

// Directions
int X[] = {-1, 0, 0, 1};
int Y[] = {0, 1, -1, 0};

char arr[21][21];

// len : number of dirty tiles + 1
// limit : 2 ^ len -1
// r, c : number of rows and columns
int len, limit, r, c;


// Returns true if current position
// is safe to visit
// else returns false
// Time Complexity : O(1)
bool safe(int x, int y)
{
    if (x >= r or y>= c or x<0 or y<0)
    return false;
    if (arr[x][y] == '#')
    return false;
    return true;
}


// runs BFS traversal at tile idx
// calulates distance to every cell
// in the grid
// Time Complexity : O(r*c)
void getDist(int idx){

    // visited array to track visited cells
    bool vis[21][21];
    memset(vis, false, sizeof(vis));

    // getting current positon
    int cx = dirty[idx].first;
    int cy = dirty[idx].second;

    // initializing queue for bfs
    queue < pair < int, int > > pq;
    pq.push({cx, cy});

    // initializing the dist to max
    // because some cells cannot be visited
    // by taking source cell as idx
    for (int i = 0;i<= r;i++)
        for (int j = 0;j<= c;j++)
            dist[i][j][idx] = INF;

    // base conditions
    vis[cx][cy] = true;
    dist[cx][cy][idx] = 0;

    while (! pq.empty())
    {
        auto x = pq.front();
        pq.pop();
        for (int i = 0;i<4;i++)
        {
        cx = x.first + X[i];
        cy = x.second + Y[i];
        if (safe(cx, cy))
        {
            if (vis[cx][cy])
                continue;
            vis[cx][cy] = true;
            dist[cx][cy][idx] = dist[x.first][x.second][idx] + 1;
            pq.push({cx, cy});
            }
        }
    }
}

// Dynamic Programming state transition recursion
// with memoization. Time Complexity: O(n*n*2 ^ n)
int solve(int idx, int mask)
{
    // goal state
    if (mask == limit)
    return dist[0][0][idx];

    // if already visited state
    if (dp[idx][mask] != -1)
    return dp[idx][mask];

    int ret = INT_MAX;

    // state transiton relation
    for (int i = 0;i<len;i++)
    {
        if ((mask & (1<<i)) == 0)
        {
            int newMask = mask | (1<<i);
            ret = min( ret, solve(i, newMask)
                + dist[dirty[i].first][dirty[i].second][idx]);
        }
    }

    // adding memoization and returning
    return dp[idx][mask] = ret;
}

void init()
{
    // initializing containers
    memset(dp, -1, sizeof(dp));
    dirty.clear();

    // populating dirty tile positions
    for (int i = 0;i<r;i++)
        for (int j = 0;j<c;j++)
        {
            if (arr[i][j] == '*')
            dirty.push_back({i, j});
        }

    // inserting ronot's location at the
    // begining of the dirty tile
    dirty.insert(dirty.begin(), {0, 0});

    len = dirty.size();

    // calculating LIMIT_MASK
    limit = (1<<len) - 1;

    // precalculating distances from all
    // dirty tiles to each cell in the grid
    for (int i = 0;i<len;i++)
    getDist(i);
}

int main(int argc, char const *argv[])
{
    // Test case #1:
    //     .....*.
    //     ...#...
    //     .*.#.*.
    //     .......

char A[4][7] = { {'.', '.', '.', '.', '.', '*', '.'},
                    {'.', '.', '.', '#', '.', '.', '.'},
                    {'.', '*', '.', '#', '.', '*', '.'},
                    {'.', '.', '.', '.', '.', '.', '.'}
                };

    r = 4; c = 7;

    cout << "The given grid : " << endl;

    for (int i = 0;i<r;i++)
    {
        for (int j = 0;j<c;j++)
        {
            cout << A[i][j] << " ";
            arr[i][j] = A[i][j];
        }
        cout << endl;
    }

    // - initializitiation
    // - precalculations
    init();

    int ans = solve(0, 1);

    cout << "Minimum distance for the given grid : ";
    cout << ans << endl;


    // Test Case #2
    //     ...#...
    //     ...#.*.
    //     ...#...
    //     .*.#.*.
    //     ...#...

    char Arr[5][7] = { {'.', '.', '.', '#', '.', '.', '.'},
                        {'.', '.', '.', '#', '.', '*', '.'},
                        {'.', '.', '.', '#', '.', '.', '.'},
                        {'.', '*', '.', '#', '.', '*', '.'},
                        {'.', '.', '.', '#', '.', '.', '.'}
                };

    r = 5; c = 7;

    cout << "The given grid : " << endl;

    for (int i = 0;i<r;i++)
    {
        for (int j = 0;j<c;j++)
        {
            cout << Arr[i][j] << " ";
            arr[i][j] = Arr[i][j];
        }
        cout << endl;
    }

    // - initializitiation
    // - precalculations
    init();
    ans = solve(0, 1);
    cout << "Minimum distance for the given grid : ";
    if (ans >= INF)
        cout << "not possible" << endl;
    else
        cout << ans << endl;

    return 0;
}


    r = 5; c = 7;

    cout << "The given grid : " << endl;

    for (int i = 0;i<r;i++)
    {
        for (int j = 0;j<c;j++)
        {
            cout << Arr[i][j] << " ";
            arr[i][j] = Arr[i][j];
        }
        cout << endl;
    }

    // - initializitiation
    // - precalculations
    init();
    ans = solve(0, 1);
    cout << "Minimum distance for the given grid : ";
    if (ans >= INF)
        cout << "not possible" << endl;
    else
        cout << ans << endl;

    return 0;
}

From engmonsh/gist:5231428

/**
 * Returns the order to visit predefined products of certain store in minimal distance
 * which returns the sequence number to visit these products
 * 
 * @author Ayman Mahgoub
 * 
 */
public class TravellingSalesMan {
  private double[][] distances;
    private short minDistances[][], paths[][];
    private ArrayList<Integer> products_visit_order;
    private int products_number_power, products_number;

    public HashMap<Product, Integer> getOrderForVisitingProducts(
            ArrayList<Product> products) {
        distances = calculateDistanceBetweenProducts(products);

        products_number = products.size();
        /*
         * you represent a subset with a bitmask, which is just an integer. If
         * location i is in the subset, bit number i is set in the integer. For
         * instance, the subset where location 3 and 4 are visited, is
         * represented by the number 24, because bit number 3 (2^3) + bit number
         * 4 (2^4) are set.
         * 
         * suppose if i take 4 vertices 1,2,3,4 then if i visit 1->2->3 then
         * (2^2)+(2^3) =12 d[1][12] will be the distance from 1->2->3
         * 
         * for 1->3->4 (2^3)+(2^4) =24 d[1][24] will be the distance from
         * 1->3->4
         * 
         * SO the matrix length is 2 ^ (product_number)
         */
        products_number_power = (int) Math.pow(2, products_number);
        minDistances = new short[products_number][products_number_power];
        paths = new short[products_number][products_number_power];

        for (int i = 0; i < products_number; i++) {
            for (int j = 0; j < products_number_power; j++) {
                minDistances[i][j] = -1;
                paths[i][j] = -1;
            }
        }

        // initialize based on distance matrix
        for (int i = 0; i < products_number; i++) {
            minDistances[i][0] = 0;
        }

        // get value of item[0][products_number_power - 2] which indicates that
        // we took all the other nodes
        getMinTraversingDistance(0, products_number_power - 2, 1);
        products_visit_order = new ArrayList<Integer>();

        getMinTraversingDistancePath(0, products_number_power - 2);

        HashMap<Product, Integer> productsOrder = new HashMap<Product, Integer>();

        int i;
        for (i = 1; i < products_number - checkout_points_numbers; i++) {
            productsOrder.put(products.get(products_visit_order.get(i - 1)), i);
        }

        minDistances = null;
        paths = null;

        return productsOrder;
    }

    private double getMinTraversingDistance(int start, int set, int level) {
        double temp = 0, result = -1;
        int masked, mask;
        if (minDistances[start][set] != -1) {
            return minDistances[start][set];
        } else {
            for (int x = 0; x < products_number; x++) {
                // minus Math.pow(2, x), means you removed this node 'x' from
                // my set to try other possibility
                mask = products_number_power - 1 - (int) Math.pow(2, x);
                masked = set & mask;

                if (masked != set) {
                        temp = distances[start][x]
                                + getMinTraversingDistance(x, masked, level + 1);
                    if (result == -1 || result > temp) {
                        result = temp;
                        paths[start][set] = (short) x;
                    }
                }
            }
            minDistances[start][set] = (short) result;
            return result;
        }
    }

    /**
     * Gets Visiting sequence by moving backwards from source node '0'
     * to destination node
     * 
     * @param start
     * @param set
     */
    private void getMinTraversingDistancePath(int start, int set) {
        if (paths[start][set] == -1) {
            return;
        }
        int x = paths[start][set];
        int mask = products_number_power - 1 - (int) Math.pow(2, x);
        int masked = set & mask;
        products_visit_order.add(x);
        getMinTraversingDistancePath(x, masked);
    }

    /**
     * Calculates all the distances (sum of horizontal and vertical distances)
     * between all nodes
     * 
     * @param products
     * @return
     */
    private double[][] calculateDistanceBetweenProducts(List<Product> products) {
        double[][] distances = new double[products.size()][products.size()];
        for (int i = 0; i < products.size(); i++) {
            for (int j = 0; j < products.size(); j++) {
                if (i != j) {
                    double distance = Math.abs(products.get(i)
                            .getAverageLocation().x
                            - products.get(j).getAverageLocation().x)
                            + Math.abs(products.get(i).getAverageLocation().y
                                    - products.get(j).getAverageLocation().y);
                    distances[i][j] = distance;
                }
            }
        }
        return distances;
    }
}

In C and C++ (by Neeraj Mishra):


#include<stdio.h>

int ary[10][10],completed[10],n,cost=0;

void takeInput()
{
    int i,j;

    printf("Enter the number of villages: ");
    scanf("%d",&n);

    printf("\nEnter the Cost Matrix\n");

    for(i=0;i < n;i++)
    {
        printf("\nEnter Elements of Row: %d\n",i+1);

        for( j=0;j < n;j++)
            scanf("%d",&ary[i][j]);

        completed[i]=0;
    }

    printf("\n\nThe cost list is:");

    for( i=0;i < n;i++)
    {
        printf("\n");

        for(j=0;j < n;j++)
            printf("\t%d",ary[i][j]);
    }
}

void mincost(int city)
{
    int i,ncity;

    completed[city]=1;

    printf("%d--->",city+1);
    ncity=least(city);

    if(ncity==999)
    {
        ncity=0;
        printf("%d",ncity+1);
        cost+=ary[city][ncity];

        return;
    }

    mincost(ncity);
}

int least(int c)
{
    int i,nc=999;
    int min=999,kmin;

    for(i=0;i < n;i++)
    {
        if((ary[c][i]!=0)&&(completed[i]==0))
            if(ary[c][i]+ary[i][c] < min)
            {
                min=ary[i][0]+ary[c][i];
                kmin=ary[c][i];
                nc=i;
            }
    }

    if(min!=999)
        cost+=kmin;

    return nc;
}

int main()
{
    takeInput();

    printf("\n\nThe Path is:\n");
    mincost(0); //passing 0 because starting vertex

    printf("\n\nMinimum cost is %d\n ",cost);

    return 0;
}

Branch And Bound | Set 6 (Traveling Salesman Problem): https://www.geeksforgeeks.org/branch-bound-set-5-traveling-salesman-problem/

results matching ""

    No results matching ""