Problem 1: Even? Odd? [25 points] [Rob Kolstad, 2009]



Дата20.08.2016
Размер162.57 Kb.
#6920
Problem 1: Even? Odd? [25 points] [Rob Kolstad, 2009]
Bessie's cruel second grade teacher has assigned a list of N (1 <= N <= 100) positive integers I (1 <= I <= 10^60) for which Bessie must determine their parity (explained in second grade as "Even... or odd?"). Bessie is overwhelmed by the size of the list and by the size of the numbers. After all, she only learned to count recently.
Write a program to read in the N integers and print 'even' on a single line for even numbers and likewise 'odd' for odd numbers.
POINTS: 25
PROBLEM NAME: evenodd
INPUT FORMAT:
* Line 1: A single integer: N
* Lines 2..N+1: Line j+1 contains I_j, the j-th integer to determine even/odd
SAMPLE INPUT (file evenodd.in):
2

1024


5931
INPUT DETAILS:
Two integers: 1024 and 5931
OUTPUT FORMAT:
* Lines 1..N: Line j contains the word 'even' or 'odd', depending on the parity of I_j
SAMPLE OUTPUT (file evenodd.out):
even

odd
OUTPUT DETAILS:


1024 is eminently divisible by 2; 5931 is not
Най-общо казано дадени са N много дълги числа, за всяко от тях трябва да се провери дали е четно или нечетно.
Analysis
The simple trick in this problems is to check whether a number is even or odd by only checking the last digit; not the entire number with modulo 2 operation.
Thus, it is not necessary to read the input as a number (or convert it to a number) but just read it as characters (or string) then check if the last digit is even or odd. Below is Rob Kolstad's solution:
#include

#include


main()

{

FILE *fin = fopen ("evenodd.in", "r");



FILE *fout = fopen ("evenodd.out", "w");

int i, n, parity;

int c;

fscanf (fin, "%d", &n);



fgetc(fin); /* gobble newline */

for (i = 0; i < n; i++) {

for (;;) {

c = fgetc(fin);

if (c == '\n') break;

parity = c % 2;

}

if (parity == 0) fprintf (fout, "even\n");



else fprintf (fout, "odd\n");

}

exit (0);



}

Примерното решение има един проблем и той е че всеки един символ, който се прочита се дели целочислено на 2, а е достатъчно да разделим само последния. Тъй като операциите по делене са скъпи, ако входните данни бяха с огромни размери, горното решение не би се вписало в даденото време. Ето мойто, подобреното решиние:
#include

#include


int N;
int main()

{

FILE *fin = fopen ("evenodd.in", "r");



FILE *fout = fopen ("evenodd.out", "w");

fscanf (fin, "%d\n", &N);

for (int i = 0; i < N; i++)

{

while(true)



{

c = fgetc(fin);

if (c == '\n') break;

last = c;

}
fprintf(fout, "%s\n", last % 2 ? "odd" : "even");

}

}


Problem 2: The Robot Plow [25 points] [Rob Kolstad (traditional), 2009]
Farmer John has purchased a new robotic plow in order to relieve him from the drudgery of plowing field after field after field. It achieves this goal but at a slight disadvantage: the robotic plow can only plow in a perfect rectangle with sides of integer length.
Because FJ's field has trees and other obstacles, FJ sets up the plow to plow many different rectangles, which might end up overlapping. He's curious as to just how many squares in his field are actually plowed after he programs the plow with various plow instructions, each of which describes a rectangle by giving its lower left and upper right x,y coordinates.
As usual, the field is partitioned into squares whose sides are parallel to the x and y axes. The field is X squares wide and Y squares high (1 <= X <= 240; 1 <= Y <= 240). Each of the I (1 <= I <= 200) plow instructions comprises four integers: Xll, Yll, Xur, and Yur (1 <= Xll <= Xur; Xll <= Xur <= X; 1 <= Yll <= Yur; Yll <= Yur <= Y) which are the lower left and upper right coordinates of the rectangle to be plowed. The plow will plow all the field's squares in the range (Xll..Xur, Yll..Yur) which might be one more row and column than would initially be assumed (depending on how you go about your assumptions, of course).
Consider a field that is 6 squares wide and 4 squares high. As FJ issues a pair of plowing instructions (shown), the field gets plowed as shown by '*' and '#' (normally plowed field all looks the same, but '#' shows which were most recently plowed):
...... **.... #####.

...... (1,1)(2,4) **.... (1,3)(5,4) #####.

...... **.... **....

...... **.... **....


A total of 14 squares are plowed.
POINTS: 25
PROBLEM NAME: rplow
INPUT FORMAT:
* Line 1: Three space-separated integers: X, Y, and I
* Lines 2..I+1: Line i+1 contains plowing instruction i which is

described by four integers: Xll, Yll, Xur, and Yur


SAMPLE INPUT (file rplow.in):
6 4 2

1 1 2 4


1 3 5 4
INPUT DETAILS:
As in the task's example.
OUTPUT FORMAT:
* Line 1: A single integer that is the total number of squares plowed
SAMPLE OUTPUT (file rplow.out):
14
Най-общо казано зададена е матрица с размери X на Y. Следват I реда, задаващи координатите на подматрици, които трябва да маркираме в главаната матрица. Иска се да се разбере колко е броя на маркираните полета в матрицата.
Analysis
This task was designed to use a two dimensional matrix. No special optimizations or clever coding were required.
The program reads in the corners of the rectangles and uses a straightforward double-neested loop to mark 'plowed' parts of the field:
for (i = 0; i < n; i++) {

fscanf (fin, "%d%d%d%d", &llx, &lly, &urx, &ury);

for (x = llx; x <= urx; x++)

for (y = lly; y <= ury; y++)

field[x][y] = 1;

The program then counts the plowed squares and outputs them.

Below is Rob Kolstad's solution:

#include

char field[250][250];
main() {

FILE *fin = fopen ("rplow.in", "r");

FILE *fout = fopen ("rplow.out", "w");

int i, n, nx, ny, x, y, llx, lly, urx, ury, count;


fscanf (fin, "%d%d%d", &nx, &ny, &n);

for (i = 0; i < n; i++) {

fscanf (fin, "%d%d%d%d", &llx, &lly, &urx, &ury);

for (x = llx; x <= urx; x++)

for (y = lly; y <= ury; y++)

field[x][y] = 1;

}

count = 0;



for (x = 1; x <= nx; x++)

for (y = 1; y <= ny; y++)

if (field[x][y])

count++;


fprintf (fout, "%d\n", count);

exit (0);

}

Problem 3: Barn Echoes [50 points] [Traditional, 2009]
The cows enjoy mooing at the barn because their moos echo back, although sometimes not completely. Bessie, ever the excellent secretary, has been recording the exact wording of the moo as it goes out and returns. She is curious as to just how much overlap there is.
Given two lines of input (letters from the set a..z, total length in the range 1..80), each of which has the wording of a moo on it, determine the greatest number of characters of overlap between one string and the other. A string is an overlap between two other strings if it is a prefix of one string and a suffix of the other string.
By way of example, consider two moos:
moyooyoxyzooo

yzoooqyasdfljkamo


The last part of the first string overlaps 'yzooo' with the first part of the second string. The last part of the second string overlaps 'mo' with the first part of the first string. The largest overlap is 'yzooo' whose length is 5.
POINTS: 50
PROBLEM NAME: echo
INPUT FORMAT:
* Lines 1..2: Each line has the text of a moo or its echo
SAMPLE INPUT (file echo.in):
abcxxxxabcxabcd

abcdxabcxxxxabcx


OUTPUT FORMAT:
* Line 1: A single line with a single integer that is the length of the longest overlap between the front of one string and end of the other.
SAMPLE OUTPUT (file echo.out):
11
OUTPUT DETAILS:
'abcxxxxabcx' is a prefix of the first string and a suffix of the second string.

По зададени два низа търсим най-дългия им общ подниз, който едновременно е префикс на първия и суфикс на втория низ.
Analysis
Rob Kolstad's solution below shows an 'overlap' routine with two inputs; calling it with line1, line2 and then line2, line1 covers both sets of possible overlap cases.

The overlap function itself treats each input string as an array of characters. It starts at character 0 in input string l2 and tries to match all of l2 in input string l1. It then starts at character 1 of input string l2 and tries to match all of l1, and so on. A good match happens when the counter through string l2 encounters the end-of-string marker (a character with value 0) that matches an end-of-string marker in l1. If that happens, 'largest' is updated.

Below is Rob Kolstad's solution:
#include

#include


int overlap (char* l1, char* l2)

{

int i, j, nmatch;



int largest = 0;

for (i = 0; l2[i]; i++) { /* start place in l2 */

nmatch = 0;

for (j = 0; l1[j] && l2[j+i]; j++) {

if (l1[j] != l2[j+i]) break;

nmatch++;

}

if (l2[j+i] == '\0' && nmatch > largest)



largest = nmatch;

}

return largest;



}
main() {

FILE *fin = fopen ("echo.in", "r");

FILE *fout = fopen ("echo.out", "w");

char line1[100];

char line2[100];

fscanf (fin, "%s %s", line1, line2);

int l1 = overlap(line1, line2);

int l2 = overlap(line2, line1);

fprintf (fout, "%d\n", l1 > l2 ? l1 : l2);

exit (0);

}

Problem 4: Papaya Jungle [80 points] [Rob Kolstad, 2009]
Bessie has wandered off the farm into the adjoining farmer's land. He raises delicious papaya fruit, which is a delicacy for cows. The papaya jungle is partitioned into a grid of squares with R rows and C columns (1 <= R <= 40, 1 <= C <= 40), as is popular in Wisconsin. Bessie can travel from a given square to any existing adjacent square whose route is parallel to the X or Y axis. So in the following diagram, if Bessie is at the square labeled "B", she can travel to any of the squares labeled "T":
.T.

TBT


.T.
Bessie always starts out by munching the papayas in square (row=1,col=1). After she's done with one square, Bessie always uses her trusty binoculars to count the low-hanging fruit in each of the adjacent squares. She then always moves to the square with the most visible uneaten fruit (a square that happily is always unique).
Sooner or later, following this rule, Bessie always ends up in square (R,C) and eats the fruit there.
Given the dimensions of the papaya jungle and the amount of fruit F_ij in each square (1 <= F_ij <= 100), determine the total number of fruit Bessie consumes for a given papaya jungle.
POINTS: 80
PROBLEM NAME: papaya
INPUT FORMAT:
* Line 1: Two space-separated integers: R and C
* Lines 2..R+1: Line i+1 describes row i of the jungle with C space-separated integers that tell how many fruit are in each square: F_i1, F_i2, ..., F_iC
SAMPLE INPUT (file papaya.in):
3 4

3 3 4 5


4 5 3 2

1 7 4 2
INPUT DETAILS:


Three rows; four columns. Bessie starts in upper left corner at the '3'.
OUTPUT FORMAT:
* Line 1: A single integer that is the total number of papayas that Bessie eats by the time she finishes off the papayas at the barn in the lower right corner at coordinate (R,C).
SAMPLE OUTPUT (file papaya.out):
39
OUTPUT DETAILS:
Bessie eats the papayas in the order given by the letters next to the numbers below:
(1,1) ---> (1,C)

(1,1) 3a 3 4g 5h (1,C)

| 4b 5c 3f 2i |

(R,1) 1 7d 4e 2j (R,C)

(R,1) ---> (R,C)
She declines to eat 4 of the papayas but consumes 39 (visiting all

but two squares of the grid).


Дадена е матрица, запълнена с цели числа с размери R на C. Трябва да намерим път от клетка (1, 1) до клетка (R, C). От текущата позиция можем да посетим само съседните с 1 по хоризонтал или вертикал клетки, като от всички тях избираме тази клетка с най-голяма стойност в нея. Не можем да посещаваме никоя клетка повече от веднъж.
Analysis
This is a simple "read the directions" problem with these components:

  • There's a row, column grid

  • Bessie starts at 1,1

  • Bessie can travel from a square to any of *four* in-bound squares

  • Bessie stops when she gets to r,c (according to the OUTPUT FORMAT)

  • Bessie chooses the best square to go to -- and she eats the papayas there, thus making that square hold 0

That just leaves I/O as a 'tricky' part, but it's not so bad, reading row 1 first, row 2 second, etc.


This program uses dr[] and dc[] as row/column incrementors so that a single loop can look at all the possible valid squares to eat.
Below is Rob Kolstad's solution:
#include

#include


int jungle [40+2][40+2]; /* guard rows and columns of 0's */

int dr[4] = {-1, 0, +1, 0};

int dc[4] = { 0, +1, 0, -1};
main() {

FILE *fin = fopen ("papaya.in", "r");

FILE *fout = fopen ("papaya.out", "w");

int i, r, c, C, R, eaten, nextrow, nextcol, row, col;

fscanf (fin, "%d%d", &R, &C);

for (r = 1; r <= R; r++)

for (c = 1; c <= C; c++)

fscanf (fin, "%d", &jungle[r][c]);

row = 1; col = 1; eaten = jungle[row][col];

jungle[row][col] = 0;

while (row != R || col != C) {

/* find biggest tree nearby */

int max = 0;

for (i = 0; i < 4; i++) {

int t = jungle[row+dr[i]][col+dc[i]];

if (t > max) {

nextrow = row+dr[i];

nextcol = col+dc[i];

max = t;

}

}



row = nextrow; col = nextcol;

eaten += jungle[row][col];

jungle[row][col] = 0; /* ate it */

}

fprintf (fout, "%d\n", eaten);



exit (0);

}
**********************************************************************


Problem 5: The Leisurely Stroll [100 points] [Rob Kolstad (traditional), 2009]
Bessie looks out the barn door at the beautiful spring day and thinks to herself, "I'd really like to enjoy my walk out to the pastures for the tender spring grass." She knows that once she leaves the barn, she will traverse a path for a while, take one of two choices that lead to other paths, follow one of them, take one of two other choices, and continue on until the path leads to a verdant pasture.
She decides to make the set of path choices that enables her to walk over the greatest number of cow paths on her way to breakfast. Given the description of these paths, determine how many cow paths she traverses, presuming that she commences choosing various paths as soon as she leaves the barn.
The farm has P (1 <= P <= 1,000) pastures that are lead to by P-1 choice-nodes (range 1..P-1) connected by paths. From the barn (which is node 1), only one set of path traversals exists to reach any choice-node or pasture.
Consider this set of paths (lines), pastures ('%'), and the highlighted ('#') route to a pasture on the right:
% %

/ /


2----% 7----8----% 2----% 7####8----%

/ \ / \ # # # #

1 5----6 9----% 1 5####6 9----%

\ \ \ \ \ \ \ #

\ % % % \ % % %

\ \


3-----% 3-----%

\ \


4----% 4----%

\ \


% %

The pasture reached from choice-node 9 is one of two that enable Bessie to traverse seven different cowpaths on the way to breakfast. These are the 'furthest' pastures from node 1, the barn.


Three integers describe each node: Cn, D1, and D2. Cn is the nodenumber (1 <= Cn <= P-1); D1 and D2 are the destinations from that node (0 <= D1 <= P-1; 0 <= D2 <= P-1). If D1 is 0, the node leads to a pasture in that direction; D2 has the same property.
POINTS: 100
PROBLEM NAME: stroll
INPUT FORMAT:
* Line 1: A single integer: P
* Lines 2..P: Line i+1 contains three space-separated integeres that describe a choice-node: Cn, D1, and D2
SAMPLE INPUT (file stroll.in):
10

7 8 0


5 0 6

9 0 0


6 0 7

3 4 0


2 5 0

8 0 9


4 0 0

1 2 3
INPUT DETAILS:


This input describes the example farm layout in the task description.
OUTPUT FORMAT:
* Line 1: A single integer that is the largest number of paths Bessie can traverse on the way to the furthest pasture.
SAMPLE OUTPUT (file stroll.out):
7
OUTPUT DETAILS:
1-2-5-6-7-8-9-P is one of the longest routes.
Разглеждаме двоично дърво, в което търсим най-дългия път от корена до кое да е листо.
Analysis
In this problem, the pastures and choice nodes are structured as a 'binary tree'. Choice nodes are internal nodes where the root node is 1, and pastures are the 'leaves' of the binary tree. We can find the longest path from 1 using depth-first search (DFS) as explained in the training pages.
Since DFS visits each node in the tree only once it requires O(P) running time. Similarly, we only keep the tree that requires O(P) memory.

This is an absolutely classic recursive algorithm. Once the tree data structure is read in, the 'visit' routine is called with a node and (current) depth (1 initiall).


The 'visit' routine finishes if we are visiting a pasture or, otherwise, continues to visit successively all the nodes accessible from the left node and then later the right node. It keeps global variable 'maxpath' updated as long paths are found.
Below is Rob Kolstad's solution:
#include

#define MAXP 1000


using namespace std;
int p, l[MAXP], r[MAXP],maxpath;

// DFS: {x-visiting node, d-depth} -- recursive

void visit(int x, int d) {

if (x==0) return; // if the node is a pasture

if (maxpath < d) maxpath=d; // update the longest path
visit (l[x],d+1); // branch to left

visit (r[x],d+1); // branch to right

}
int main () {

// read in the data:

ifstream f("stroll.in");

f >> p;


for (int i = 0; i < p; i++) {

int a, b, c;

f >> a >> b >> c;

l[a] = b;

r[a] = c;

}

f.close();


// find the longest path

visit (1,1);


// write the answer

ofstream f ("stroll.out");

f << maxpath << "\n";

f.close();

}
Двоичното дърво е частен случай на граф. Нека обобщим задачата за граф: Измежду всички прости пътища от връх 1 до N+1 се търси най-дългия по брой на върховете.
Алгоритъмът за намиране на всички прости пътища между два върха, който аз използвах за решение на тази задача е детайлно обяснен в „Програмиране = ++Aлгоритми”, глава 5, стр. 264-266. Ето и моето решение:

#include

#define MAXN 1005
int N, startV = 1, endV, count, answer = 0;

bool A[MAXN][MAXN], used[MAXN];


void allDFS(int i, int j)

{

if (i == j)



{

if(count > answer) answer = count;

return;

}
used[i] = true;



count++;

for (int k = 0; k < N; k++)

if (A[i][k] && !used[k]) allDFS(k, j);

used[i] = false;

count--;

}
int main()

{

FILE * f = fopen("stroll.in", "r");



fscanf(f, "%d\n",&N);
int a, b, c;

for(int i = 0;i < N - 1;i++)

{

fscanf(f, "%d %d %d\n", &a, &b, &c);


if(b > 0)

{

A[a - 1][b - 1] = true;



A[b - 1][N - 1] = true;

}
if(c > 0)

{

A[a - 1][c - 1] = true;



A[c - 1][N - 1] = true;

}

}


for (int i = 0, count = 0; i < N; i++) used[i] = 0;

allDFS(startV - 1, N - 1);


FILE * fout = fopen("stroll.out", "w");
fprintf(fout, "%d\n", answer);

return 0;

}
Problem 8: Bessie's Weight Problem [250 points] [Rob Kolstad (traditional), 2009]
Bessie, like so many of her sisters, has put on a few too many pounds enjoying the delectable grass from Farmer John's pastures. FJ has put her on a strict diet of no more than H (5 <= H <= 45,000) kilograms of hay per day.
Bessie can eat only complete bales of hay; once she starts she can't stop. She has a complete list of the N (1 <= N <= 500) hay bales available to her for this evening's dinner and, of course, wants to maximize the total hay she consumes. She can eat each supplied bale only once, naturally (though duplicate weight values might appear in the input list; each of them can be eaten one time).
Given the list of hay bale weights W_i (1 <= W_i <= H), determine the maximum amount of hay Bessie can consume without exceeding her limit of H kilograms (remember: once she starts on a hay bale, she eats it all).
POINTS: 250
PROBLEM NAME: diet
INPUT FORMAT:
* Line 1: Two space-separated integers: H and N
* Lines 2...N+1: Line i+1 describes the weight of hay bale i with a single integer: W_i
SAMPLE INPUT (file diet.in):
56 4

15

19



20

21
INPUT DETAILS:


Four hay bales of weight 15, 19, 20, and 21. Bessie can eat as many as she wishes without exceeding the limit of 56 altogether.
OUTPUT FORMAT:
* Line 1: A single integer that is the number of kilograms of hay that Bessie can consume without going over her limit.
SAMPLE OUTPUT (file diet.out):
56
OUTPUT DETAILS:
Bessie can eat three bales (15, 20, and 21) and run right up to the limit of 56 kg.

Трябва да се намери най-голямата сума, която може да се образува от зададени числа и е по-малка или равна на зададено число H.
Analysis

Динамично оптимиране.

Ще използваме характеристичен масив sum, в който sum[j] е 1 ако j може да бъде получено, като сума на някои от дадените числа. Търсим максималната сума, която може да се получи, като сума на кои да е от дадените числа. Първоначално масивът sum е занулен, с изключение на нулевия му елемент.

За всяко поредно i от зададените числа, проверяваме дали разликата на текущо-намаляващата сума j (започвайки от Н докато j не надминава i-тото число + 1) и поредното i e вече образувано, ако да, това означава, че и сума j може да бъде образувана. Разбира се установяваме sum[weight[i]] и в 1.

След като сме образували всевъзможните суми, обхождаме масива sum декрементално, започвайки от H. Индексът на първия му елемент, чиято стойност е 1 е отговорът.

Сложността на алгоритъма е O(N*Н).

#include "stdio.h";


#define MAXH 45010

#define MAXN 510


int weight[MAXN], N, H;

char sum[MAXH] = {0};


int solve()

{

sum[0] = 1;



for(int i = 0;i < N;i++)

{

for(int j = H;j > weight[i] + 1;j--)



if(sum[j - weight[i]])

sum[j] = 1;


sum[weight[i]] = 1;

}
for(int i = H;i >= 0;i--)

if(sum[i])

return i;

}
int main()

{

FILE * f = fopen("diet.in", "r");



fscanf(f, "%d %d\n", &H, &N);
for(int i = 0;i < N;i++)

fscanf(f, "%d\n", &weight[i]);


FILE * fout = fopen("diet.out", "w");

fprintf(fout, "%d\n", solve());


return 0;

}

Problem 9: Heat Wave [300 points] [Rob Kolstad (traditional), 2009]


The good folks in Texas are having a heat wave this summer. Their Texas Longhorn cows make for good eating but are not so adept at creating creamy delicious dairy products. Farmer John is leading the charge to deliver plenty of ice cold nutritious milk to Texas so the Texans will not suffer the heat too much.
FJ has studied the routes that can be used to move milk from Wisconsin to Texas. These routes have a total of T (1 <= T <= 2,500) towns conveniently numbered 1..T along the way (including the starting and ending towns). Each town (except the source and destination towns) is connected to at least two other towns by bidirectional roads that have some cost of traversal (owing to gasoline consumption, tolls, etc.). Consider this map of seven towns; town 5 is the source of the milk and town 4 is its destination (bracketed integers represent costs to traverse the route):
[1]----1---[3]-

/ \


[3]---6---[4]---3--[3]--4

/ / /|


5 --[3]-- --[2]- |

\ / / |


[5]---7---[2]--2---[3]---

| /


[1]------
Traversing 5-6-3-4 requires spending 3 (5->6) + 4 (6->3) + 3 (3->4) = 10 total expenses.
Given a map of all the C (1 <= C <= 6,200) connections (described as two endpoints R1i and R2i (1 <= R1i <= T; 1 <= R2i <= T) and costs (1 <= Ci <= 1,000), find the smallest total expense to traverse from the starting town Ts (1 <= Ts <= T) to the destination town Te (1 <= Te <= T).
POINTS: 300
PROBLEM NAME: heatwv
INPUT FORMAT:
* Line 1: Four space-separated integers: T, C, Ts, and Te
* Lines 2..C+1: Line i+1 describes road i with three space-separated integers: R1i, R2i, and Ci
SAMPLE INPUT (file heatwv.in):
7 11 5 4

2 4 2


1 4 3

7 2 2


3 4 3

5 7 5


7 3 3

6 1 1


6 3 4

2 4 3


5 6 3

7 2 1
INPUT DETAILS:


As in the sample map.
OUTPUT FORMAT:
* Line 1: A single integer that is the length of the shortest route from Ts to Te. It is guaranteed that at least one route exists.
SAMPLE OUTPUT (file heatwv.out):
7
OUTPUT DETAILS:
5->6->1->4 (3 + 1 + 3)
Търси се най-късия (по сума на ребрата) път от стартов връх до краен.

Analysis
This is a straightforward 'shortest path' problem solved Dijsktra's Algorithm on an adjacency matrix. A distance array of towns will help us to keep the distances from the starting town to the other towns during the search. The steps are as follows:


  1. We first start at the departure town Ts where its distance is 0, and the rest of the towns are not reachable yet, i.e., the distances of all towns are infinite.

  2. Update distances of the neighbor towns of the current town (dist[i] = min{dist[i],dist[current]+mat[current][i]} - i is neighbor of current).

  3. Always choose the shortest unvisited town from the departure town (current = min_i{dist[i]} - where i is unvisited).

  4. If the town is not the destination, return step 2.

In step 3, note that the shortest unvisited town has to be a neighbor of one of the explored towns since initially all towns are unreachable, later they become reachable when a neighbor town is visited in step 2. The algorithm with adjacency matrix requires O(T^2) running time since each node is visited once and all the neighbors of each node is explored using an adjacency matrix. Memory complexity is also O(T^2) since it requires adjacency matrix. The time and memory complexity can be reduced to O(C + T log T) by using a priority queue and an adjacency list however we don't need in this question.

Below is Rob Kolstad's solution:
#include
#define MAXN 2500

#define INF 1000000000


using namespace std;
short T,Ts,Te,mat[MAXN][MAXN];

int dist[MAXN];

bool used[MAXN];
void readFile(char *inpFile) {

ifstream f(inpFile);

int a, b, c, d;
f >> T >> c >> Ts >> Te;

Ts--;


Te--;

for (int i = 0; i < c; i++) {

f >> a >> b >> d;

mat[--a][--b] = mat[b][a] = d;

}

f.close ();



}
// Dijkstra with adjacency matrix implementation

void solve () {

/* initialize the distance list of the towns */

for (int i = 0; i < T; i++)

dist[i] = INF;

dist[Ts] = 0; /* start from the departure town with 0 distance */


for ( ; ; ) {

/* choose the shortest path from the list among unexplored towns */

int min = -1;

for (int i = 0; i < T; i++)

if (!used[i] && (min<0 || dist[min] > dist[i]))

min = i;
used[min] = true;

if (min == Te) /* done if destination town */

break;
/* update path */

for (int i = 0; i < T; i++)

if (mat[min][i] && dist[i] > dist[min] + mat[min][i])

dist[i] = dist[min] + mat[min][i];

}

}


int main() {

readFile ("heatwv.in");

solve ();

ofstream f ("heatwv.out);

f << dist[Te] << "\n";

f.close ();

return 0;

}

Следва реализация на алгоритъма на Dijsktra със сложност O(C + T log T), която лесно може да се пpигоди за решение на дадената задача:

#include

#include

#include

using namespace std;


#define MAX 100

#define MP(x, y) make_pair((x), (y))


int E, V, dist[MAX], parent[MAX];

bool vis[MAX];

vector
> edges[MAX];
void printPath(int s, int j)

{

if (parent[j] != s)



printPath(s, parent[j]);

printf("%d ", j + 1);

}
void printResult(int s)

{

for (int i = 0; i < E; i++)



{

if (dist[i] != INT_MAX && i != s)

{

printf("%d -> %d (%d): ", s + 1, i + 1, dist[i]);



printf("%d ", s + 1);

printPath(s, i);

printf("\n");

}

}



}
void read()

{

freopen("dijikstra.in", "r", stdin);



int u, v, c;

scanf("%d %d", &E, &V);

for(int i = 0;i < V;i++)

{

scanf("%d %d %d", &u, &v, &c);



u--; v--;
edges[u].push_back(MP(v, c));

//edges[v].push_back(MP(u, c)); //if the graph is b-directional

}

}
void dijkstra(int s)



{

int i, u, v, w;


dist[s] = 0;

parent[s] = -1;


priority_queue
> pq;

pq.push(MP(-dist[s], s));


while (!pq.empty())

{

u = pq.top().second;



pq.pop();

if (vis[u])

continue;
vis[u] = true;

for(i = 0; i < edges[u].size(); i++)

{

v = edges[u][i].first;



w = edges[u][i].second;
if (dist[u] + w < dist[v])

{

dist[v] = dist[u] + w;



parent[v] = u;

pq.push(MP(-dist[v], v));

}

}

}



}
void init()

{

for(int i = 0;i < E;i++)



{

dist[i] = INT_MAX;

vis[i] = false;

}

}


int main()

{

int startV = 5;



read();

init();


dijkstra(startV);

printResult(startV);


return 0;

}

Каталог: 2010 -> WCP
2010 -> Регионален инспекторат по образованието – бургас съюз на математиците в българия – секция бургас дванадесето състезание по математика
2010 -> Януари – 2010 тест зад Резултатът от пресмятане на израза А. В, където
2010 -> Библиографски опис на публикациите, свързани със славянските литератури в списание „Панорама” /1980 – 2011
2010 -> Специалисти от отдел кнос, Дирекция „Здравен Контрол при риокоз русе, извършиха проверки в обектите за съхранение и продажба на лекарствени продукти за хуманната медицина на територията на град Русе
2010 -> 7 клас отговори на теста
2010 -> Конкурс за научно звание „професор" по научна специалност 05. 02. 18 „Икономика и управление" (Стопанска логистика) при унсс, обявен в дв бр. 4/ 15. 01. 2010
2010 -> Код на училище Име на училище


Сподели с приятели:




©obuch.info 2024
отнасят до администрацията

    Начална страница