cmallocdynamic-programmingdynamic-memory-allocationcalloc

What's the reason for the occurrence of Segmentation fault (core dumped)?


I use C language, and apply Dynamic Programming to solve the Travelling salesman problem. There is such a problem on ZeroJudge, An Online Judge System For Beginners, but I get Segmentation fault (core dumped) on the 13th, 14th, and 15th test cases. I have checked my code, but I can’t find the problem.

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#define min(a, b)(a > b ? b : a)
void travel();
int **map,**dp,n;
main()
{
    scanf("%d", &n);
    map = (int **)calloc(n, sizeof(int *));
    dp = (int **)calloc(n, sizeof(int *));
    for(int i = 0 ; i < n ; i++)
    {
        map[i] = (int *)calloc(n, sizeof(int));
        dp[i] = (int *)calloc((1 << (n - 1)), sizeof(int));
    }
    int distance;
    for(int i = 0 ; i < n ; i++)
    {
        for(int j = 0 ; j < n ; j++)
        {
            scanf("%d", &distance);
            map[i][j] = distance;
        }
        dp[i][0] = map[i][0];
    }
    travel();
    printf("%d\n", dp[0][(1 << (n - 1)) - 1]);
    free(map);
    free(dp);
}
void travel()
{
    for(int j = 1 ; j < 1 << (n - 1) ; j++) 
    {
        for(int i = 0 ; i < n ; i++)   
        {
            dp[i][j] = INT_MAX;
            if(j >> (i - 1) & 1)  
            {
                continue;
            }
            for(int k = 1 ; k < n ; k++)
            {
                if(!(j >> (k - 1) & 1))
                {
                    continue;
                }
                dp[i][j] = min(dp[i][j], map[i][k] + dp[k][j ^ (1 << (k - 1))]);
            }
        }
    }
}

Content

Given a set of cities and the distances between each pair of cities, find the shortest distance sum of a tour that starts from a city, visits all the cities without repetition, and returns to the starting city.
For example, the visiting order is 1-2-3-4-1. The distance sum is 10 + 25 + 30 + 15 = 80.

Input Description

There is only one set of test data. The first line of each set has an integer N, indicating that there are N cities. Then there will be N lines, each line has N non-negative integers Di,j indicating the distance from node i to node j. If Di,j = 0, it is considered that there is no edge.
You can assume that each edge may be unidirectional, and guarantee that there is at least one TSP path.
* 3 < N ≤ 35
* 0 distance between any pair of cities ≤ 10000

Output Description

Output a line of minimum distance sum.

Example input #1

4
0 10 15 20
10 0 35 25
15 35 0 30
20 25 30 0

Example Output #1

80

Solution

  • The problem statement says “3 < N ≤ 35”. The program uses 1 << (n - 1) in several places, where n contains the value of N. This shifts the int value 1 by as much as 34 bits. However, int is commonly 32 bits in current C implementations, so shifting by more than 30 bits overflows, and the behavior is not defined by the C standard.

    Further, the program attempts to allocate space for an array of 1 << (n - 1) int elements, in calloc((1 << (n - 1)), sizeof(int)). This may fail due to being too large a request, especially since it is repeated N times. Or the overflow in 1 << (n - 1) may result in insufficient memory being requested.

    You need a new algorithm that does not attempt to use so much memory.