「中興捧月」程序設計大賽之——教師家訪安排

 

 

輸入文件:student.txt    distance.txtios

 

你是小學某班主任,須要安排週六進行家訪。因而打電話與家長聯繫,他們表示雖然比較忙,但仍是會爲你抽出一點時間。因爲有些家長時間上有衝突,而且一天內不能拜訪全部家長,你須要一個程序安排一天的工做,使得你能夠拜訪最多的家長。注意, 若是與某個家長見面,拜訪時間不得少於45分鐘(M,不然可能引發家長不滿意。另外從一個家長到另一個家長鬚要花費一些時間。測試

 

Input1:  student.txtthis

輸入包括多個測試數據,每一個測試數據開頭是一個整數n1<=n<=40),表示家長總數。接下來n行每行包括三個正整數mstm表示家長的序號,st分別表示該家長空閒時間段的起始時間和終止時間,s小於t。注意兩個數字的最後兩位表示分鐘。好比1645 表示1645分。樣本以下:spa

6code

1   800    1100    orm

2   800    900ci

3   845    1000element

4   1300  1400get

5   1345  1800it

6   1500  1700

 

Input2:  distance.txt

第一行爲 家長總數隨後爲一個二維表格,記錄每2個用戶之間的距離。第二行和第一列數據爲家長順序編號。其餘數據爲2個家長之間的距離。樣本以下:

6

0    1    2    3    4      5     6

1    0    1    2    4      3     1

2    1    0    3    5      3     2

3    2    3    0    6      1     3

4    4    5    6    0      4     14

5    3    3    1    4      0     15

6    1    2    3    14    15   0

 

Output:

拜訪的家長總數

拜訪的家長的序號和開始結束時間

 

我獲得的結果爲(時間按照分鐘計算):

因爲預賽時間尚未結束,故不能將代碼公佈,有興趣的朋友能夠想一想。

 

現將代碼公佈以下(2010-08-11):

 

/*****************************************************************************
 *                                 constants.h
 *
 * Some constants.
 *
 * Zhang Ming, 2010-05
 *****************************************************************************/


#ifndef	CONSTANTS_H
#define CONSTANTS_H


#include <climits>


const int   INFTY = INT_MAX;
const int   VISITTIME   = 45;

const int   INITSIZE    = 20;
const int   EXTFACTOR   = 2;


#endif
// CONSTANTS_H

 

#ifndef ALLOCATE_2D_MATRIX_H_
#define ALLOCATE_2D_MATRIX_H_


template<typename Type>
inline void make2DArray(Type **&x,int rows,int cols)
{
    x = new Type*[rows];
    for(int i = 0; i < rows; ++i)
        x[i] = new Type[cols];
}

template<typename Type>
inline void delete2DArray(Type**& x,int rows)
{
    for(int i = 0; i < rows; ++i)
        delete [] x[i];

    delete [] x;
    x = 0;
}


#endif
// ALLOCATE_2D_MATRIX_H_

 

/*****************************************************************************
 *                                    stack.h
 *
 * Stack class.
 *
 * Zhang Ming, 2010-05
 *****************************************************************************/


#ifndef STACK_H
#define STACK_H


#include <iostream>
#include <cstdlib>
#include "constants.h"


using namespace std;


template <typename Type>
class Stack
{

public:

    explicit Stack( int maxSize = INITSIZE );
    Stack( const Stack<Type> &s );
    ~Stack();
    Stack<Type>& operator=( const Stack<Type> &s );

    inline bool isEmpty() const;
    inline void push( const Type &x );
    inline Type pop();

private:

    int top;
    int capacity;
    Type *elements;

    void handleOverflow();

};
// class Stack


/**
 * constructors and destructor
 */
template <typename Type>
Stack<Type>::Stack( int maxSize ) : top (-1), capacity(maxSize)
{
    elements = new Type[maxSize];
    if( !elements )
    {
        cerr << "Out of memory!" << endl;
        exit(1);
    }
};

template <typename Type>
Stack<Type>::Stack( const Stack<Type> &s )
{
    top = s.top;
    capacity = s.capacity;

    elements = new Type[capacity];
    for( int i=0; i<=top; ++i )
        elements[i] = s.elements[i];
}

template <typename Type>
Stack<Type>::~Stack()
{
    top = -1;
    capacity = INITSIZE;
    delete []elements;
}


/**
 * Overload copy assignment operation.
 */
template <typename Type>
Stack<Type>& Stack<Type>::operator=( const Stack<Type> &s )
{
    top = s.top;
    capacity = s.capacity;

    elements = new Type[capacity];
    for( int i=0; i<=top; ++i )
        elements[i] = s.elements[i];

    return *this;
}


/**
 * If the stack is empty, return true.
 */
template <typename Type>
inline bool Stack<Type>::isEmpty() const
{
    return ( top == -1 );
}


/**
 * Push an element into the stack.
 */
template <typename Type>
inline void Stack<Type>::push( const Type &x )
{
    elements[++top] = x;
    if( top == capacity-1 )
        handleOverflow();
};


/**
 * Pop an element out of stack.
 */
template <typename Type>
inline Type Stack<Type>::pop()
{
    if( !isEmpty() )
        return elements[top--];
    else
    {
        cerr << "The stack is empty!" << endl << endl;
        return Type();
    }
};


/**
 * If the capability of the stack exceeds the initial size,
 * make it double.
 */
template <typename Type>
void Stack<Type>::handleOverflow()
{
    capacity = EXTFACTOR * capacity ;

    Type *newArray = new Type[capacity];
    if( newArray == NULL )
    {
        cerr << "Out of memory!" << endl;
        exit(1);
    }

    for( int i=0; i<=top; ++i )
        newArray[i] = elements[i];

    delete []elements;
    elements = newArray;
};


#endif
// STACK_H

 

/*****************************************************************************
 *                                    binaryheap.h
 *
 * Minimum binary heap class.
 *
 * Zhang Ming, 2010-05
 *****************************************************************************/


#ifndef BINARYHEAP_H
#define BINARYHEAP_H


#include <iostream>
#include <cstdlib>
#include "constants.h"


using namespace std;


template <typename Type>
class BinaryHeap
{

public:

    explicit BinaryHeap( int maxSize = INITSIZE );
    BinaryHeap( const BinaryHeap<Type> &h );
    BinaryHeap( Type *array, int length );
    ~BinaryHeap();
    BinaryHeap<Type>& operator=( const BinaryHeap<Type> &h );

    inline bool isEmpty() const;
    inline void deleteMin( Type &minItem );
    inline void adjust();
    inline int  getSize() const;
    inline Type* getEntries() const;

private:

    Type *elements;
    int currentSize;
    int capacity;

    void filterDown( int hole );
    void filterUp( int hole );
    void handleOverflow();

};
// class BinaryHeap


/**
 * constructors and destructor
 */
template <typename Type>
BinaryHeap<Type>::BinaryHeap( int maxSize )
{
    capacity = maxSize;

    elements = new Type[capacity+1];
    if( elements == NULL )
        cerr << "Out of memory!" << endl;

    currentSize = 0;
}

template <typename Type>
BinaryHeap<Type>::BinaryHeap( Type *array, int length )
{
    capacity = ( INITSIZE > length ) ? INITSIZE : length;

    elements = new Type[capacity+1];
    if( elements == NULL )
        cerr << "Out of memory!" << endl;

    for( int i=0; i<length; ++i )
        elements[i+1] = array[i];

    currentSize = length;
    for( int i=currentSize/2; i>0; --i )
        filterDown( i );
}

template <typename Type>
BinaryHeap<Type>::BinaryHeap( const BinaryHeap<Type> &h )
{
    currentSize = h.currentSize;
    capacity = h.capacity;

    elements = new Type[capacity];
    for( int i=1; i<=currentSize; ++i )
        elements[i] = h.elements[i];
}

template <typename Type>
BinaryHeap<Type>::~BinaryHeap()
{
    currentSize = 0;
    capacity = INITSIZE;
    delete []elements;
}


/**
 * Overload copy assignment operation.
 */
template <typename Type>
BinaryHeap<Type>& BinaryHeap<Type>::operator=( const BinaryHeap<Type> &h )
{
    currentSize = h.currentSize;
    capacity = h.capacity;

    elements = new Type[capacity];
    for( int i=1; i<=currentSize; ++i )
        elements[i] = h.elements[i];

    return *this;
}


/**
 * If the heap is empty, return true.
 */
template <typename Type>
inline bool BinaryHeap<Type>::isEmpty() const
{
    return currentSize == 0;
}


/**
 * Remove the minimum item and place it in minItem.
 */
template <typename Type>
inline void BinaryHeap<Type>::deleteMin( Type &minItem )
{
    if( !isEmpty() )
    {
        minItem = elements[1];
        elements[1] = elements[currentSize--];
        filterDown( 1 );
    }
    else
        cerr << "The heap is empty!" << endl << endl;
}


/**
 * Adjust the array to be a heap.
 */
template <typename Type>
inline void BinaryHeap<Type>::adjust()
{
    for( int i=currentSize/2; i>0; --i )
        filterDown(i);
}


/**
 * Get current size of the heap.
 */
template <typename Type>
inline int BinaryHeap<Type>::getSize() const
{
    return currentSize;
}


/**
 * Get the element pointer of the heap.
 */
template <typename Type>
inline Type* BinaryHeap<Type>::getEntries() const
{
    return elements;
}


/**
 * Percolate down the heap, begin at "hole".
 */
template <typename Type>
void BinaryHeap<Type>::filterDown( int hole )
{
    int child;
    Type tmp = elements[hole];

    for( ; 2*hole<=currentSize; hole=child )
    {
        child = 2*hole;

        if( child != currentSize && elements[child+1] < elements[child] )
            child++;

        if( elements[child] < tmp )
            elements[hole] = elements[child];
        else
            break;
    }

    elements[hole] = tmp;
}


/**
 * Percolate up the heap, begin at "hole".
 */
template <typename Type>
void BinaryHeap<Type>::filterUp( int hole )
{
    Type tmp = elements[hole];

    for( ; hole>1 && tmp<elements[hole/2]; hole/=2 )
        elements[hole] = elements[hole/2];

    elements[hole] = tmp;
}


/**
 * If the capability of the heap exceeds the initial size, make it double.
 */
template <typename Type>
void BinaryHeap<Type>::handleOverflow()
{
    capacity = EXTFACTOR * capacity;

    Type *newArray = new Type[capacity+1];
    if( newArray == NULL )
    {
        cerr << "Out of memory!" << endl;
        exit(1);
    }

    for( int i=1; i<=currentSize; ++i )
        newArray[i] = elements[i];

    delete []elements;
    elements = newArray;
};


#endif
// BINARYHEAP_H

 

/*****************************************************************************
 *                                    student.h
 *
 * The student class with comparison operators.
 *
 * Zhang Ming, 2010-05
 *****************************************************************************/


#ifndef STUDENT_H
#define STUDENT_H


#include <iostream>
#include "constants.h"


using namespace std;


class Student
{

public:

    int number;
    int key;
    int stopTime;

    Student() : number(0), key(0), stopTime(0)
    { }

    Student( int num, int k, int stop )
    {
        number = num;
        key = k;
        stopTime = stop;
    }

    ~Student()
    {}

    void operator=( const Student &stu )
    {
        number = stu.number;
        key = stu.key;
        stopTime = stu.stopTime;
    }

    inline bool operator==( const Student &stu )
    {   return key == stu.key;   }

    inline bool operator<( const Student &stu )
    {
        if( key == stu.key )
            return stopTime < stu.stopTime;
        else
            return key < stu.key;
    }

    inline bool satisfy()
    {
        return stopTime-key >= 45;
    }

    friend ostream& operator<<( ostream &out, Student &stu )
    {
        out << stu.number << "    " << stu.key << "    " << stu.stopTime << endl;
        return out;
    }

};
// struct Student


#endif
// STUDENT_H

 

#ifndef FLOYD_SHORTEST_PASH_H_
#define FLOYD_SHORTEST_PASH_H_


#include <cstdlib>
#include "constants.h"


template <typename Type>
void floyd(Type **shortestDist, Type **directDist, int n, int **path)
{
	int i=0, j=0, k=0;
	for (i=0; i<n; ++i)
	{
		for (j=0; j<n; ++j)
		{
			shortestDist[i][j] = directDist[i][j];
			if (i!=j && directDist[i][j]<INFTY)
			{
				path[i][j] = i;
			}
			else
				path[i][j] = -1;
		}
	}

	for (k=0; k<n; ++k)
	{
		for (i=0; i<n; ++i)
		{
			for (j=0; j<n; ++j)
			{
				if (shortestDist[i][k]+shortestDist[k][j] < shortestDist[i][j])
				{
					shortestDist[i][j] = shortestDist[i][k]+shortestDist[k][j];
					path[i][j] = path[k][j];
				}
			}
		}
	}
}


template <typename Type>
void floyd(Type **shortestDist, Type **directDist, int n)
{
	int i=0, j=0, k=0;
	for (i=0; i<n; ++i)
	{
		for (j=0; j<n; ++j)
		{
			shortestDist[i][j] = directDist[i][j];
		}
	}

	for (k=0; k<n; ++k)
	{
		for (i=0; i<n; ++i)
		{
			for (j=0; j<n; ++j)
			{
				if (shortestDist[i][k]+shortestDist[k][j] < shortestDist[i][j])
				{
					shortestDist[i][j] = shortestDist[i][k]+shortestDist[k][j];
				}
			}
		}
	}
}


template <typename Type>
void floyd(Type **dist, int n)
{
	int i=0, j=0, k=0;
	for (k=0; k<n; ++k)
	{
		for (i=0; i<n; ++i)
		{
			for (j=0; j<n; ++j)
			{
				if (dist[i][k]+dist[k][j] < dist[i][j])
				{
					dist[i][j] = dist[i][k]+dist[k][j];
				}
			}
		}
	}
}


#endif
// FLOYD_SHORTEST_PASH_H_

 

/*****************************************************************************
 *                                    visit.h
 *
 * Find the visit routine.
 *
 * Zhang Ming, 2010-05
 *****************************************************************************/


#ifndef VISIT_H
#define VISIT_H


#include "student.h"
#include "stack.h"
#include "binaryheap.h"


int visit( BinaryHeap<Student> &h, Stack<Student> &s, int **dist )
{
    if( h.isEmpty() )
        return 0;

    Student stu, tmp;
    h.deleteMin(stu);
    if( !stu.satisfy() )
        return visit( h, s, dist );

    int newStart,
        thisNum,
        curSize = h.getSize();

    if( curSize > 0 )
    {
        Stack<Student> ss(curSize);
        Stack< BinaryHeap<Student> > hs(curSize);
        Student *p = h.getEntries();
        Student *q = new Student[curSize];

        for( int i=1; i<=curSize; ++i )
        {
            newStart = stu.key + VISITTIME + dist[stu.number-1][p[i].number-1];
            if( newStart > p[i].key )
            {
                ss.push(p[i]);

                tmp = p[i];
                for( int j=1; j<=curSize; ++j )
                    q[j-1] = p[j];
                q[i-1] = stu;
                for( int j=0; j<curSize; ++j )
                {
                    newStart = tmp.key + VISITTIME + dist[tmp.number-1][q[j].number-1];
                    if( newStart > q[j].key )
                        q[j].key = newStart;
                }

                hs.push( BinaryHeap<Student>(q,curSize) );
            }
        }

        for( int i=1; i<=curSize; ++i )
        {
            newStart = stu.key + VISITTIME + dist[stu.number-1][p[i].number-1];
            if( newStart > p[i].key )
                p[i].key = newStart;
        }
        h.adjust();

        thisNum = visit( h, s, dist );

        while( !hs.isEmpty() )
        {
            Stack<Student> os(curSize);
            BinaryHeap<Student> oh = hs.pop();
            int otherNum = visit( oh, os, dist );
            if( otherNum > thisNum )
            {
                s = os;
                thisNum = otherNum;
                stu = ss.pop();
            }
            else
                ss.pop();
        }
    }
    else
        thisNum = 0;

    stu.stopTime = stu.key + VISITTIME;
    s.push(stu);
    return thisNum + 1;
}


#endif
// VISIT_H

 

#ifndef FILE_READER_H_
#define FILE_READER_H_


void read2Files(char *stuFile, char* distFile, int **&info, int **&dist, int &n);

void printMatrix(int **matrix, int row, int col=-1);


#endif
// FILE_READER_H_

 

#include "fileReader.h"
#include "matrixAllocate.h"
#include <cstdio>
#include <conio.h>
#include <cstdlib>


void read2Files(char *stuFile, char* distFile, int **&info, int **&dist, int &n)
{
	FILE *fp = fopen(stuFile, "rt");
	int id, s, t, hour, minute;
	int i, j;
	if(fp)
	{
		fscanf(fp, "%d", &n);

		make2DArray(info, n, 3);

		for(i = 0; i < n; i++)
		{
			fscanf(fp, "%d%d%d", &id, &s, &t);
			info[i][0] = id;
			hour = s / 100;
			minute = s % 100;
			s = hour * 60 + minute;
			info[i][1] = s;
			hour = t / 100;
			minute = t % 100;
			t = hour * 60 + minute;
			info[i][2] = t;
		}
	}
	else
	{
		printf("Can't open file: \"%s\"!\n", stuFile);
		exit(1);
	}

	int r, temp;
	FILE *fpd = fopen(distFile, "rt");
	if(fpd)
	{
		fscanf(fpd, "%d", &r);
		if(r != n)
		{
			printf("\"%s\" and \"%s\" have diffierent row number!\n", stuFile, distFile);
			exit(1);
		}

		make2DArray(dist, r, r);

		//fseek(fp, 7, 1);
		for(i = 0; i <= r; i++)
			fscanf(fpd, "%d", &temp);
		for(i = 0; i < r; i++)
		{
			fscanf(fpd, "%d", &temp);
			for(j = 0; j < r; j++)
			{
				fscanf(fpd, "%d", &dist[i][j]);
			}
		}
	}
	else
	{
		printf("Can't open file: \"%s\"!\n", distFile);
		exit(1);
	}
}


void printMatrix( int **matrix, int row, int col )
{
	for(int i = 0; i < row; ++i)
	{
		for(int j = 0; j < col; ++j)
		{
			printf("%5d", matrix[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}

 

/*****************************************************************************
 *                               visit_test.cpp
 *
 * Visiting testing.
 *
 * Zhang Ming, 2010-05
 *****************************************************************************/


#include <iostream>
#include "matrixAllocate.h"
#include "fileReader.h"
#include "floyd.h"
#include "visit.h"


using namespace std;


int main()
{
    int n,  totNum = 0;
    int **time = 0;	// n * 3
	int **dist = 0;	// n * n
	int **shortestDist = 0;// n * n
	int **path = 0;// n * n
	char *fileName1 = (char*) "student.txt";
	char *fileName2 = (char*) "distance.txt";

	read2Files( fileName1, fileName2, time, dist, n );
	cout << "The visiting time information: " << endl;
	printMatrix( time, n, 3);
	cout << "The visiting distance information: " << endl;
	printMatrix( dist, n, n);
	make2DArray( shortestDist, n, n);
	make2DArray( path, n, n);
	floyd(dist, n);
	cout << "The shortest visiting distance information: " << endl;
	printMatrix(dist, n, n);

    Student x, *Stu = new Student[n];
    for( int i=0; i<n; ++i )
    {
        Stu[i].number = time[i][0];
        Stu[i].key = time[i][1];
        Stu[i].stopTime = time[i][2];
    }

    Stack<Student> s(n);
    BinaryHeap<Student> heap( Stu, n );

    totNum = visit( heap, s, dist );
    cout << "The total number of visited students is: " << totNum << endl << endl;
    cout << "The visiting order and time information: " << endl;
    while( !s.isEmpty() )
    {
        x = s.pop();
        cout << "    " << x;
    }

    cout << endl;
    return 0;
}
相關文章
相關標籤/搜索