Pháo hoa cầu chì


13

Tổng quat

Đưa ra một danh sách pháo hoa a-zvà thời gian 3-78, sắp xếp chúng với cầu chì để làm cho tất cả chúng sáng lên vào đúng thời điểm.

Một dòng đầu vào được đưa ra dưới dạng các chữ cái và số được phân tách bằng dấu cách:

a 3 b 6 c 6 d 8 e 9 f 9

Ví dụ đó cho thấy pháo hoa acần sáng vào thời gian 3, bccả lúc 6, dlúc 8, lúc efcả lúc 9. Mỗi dòng tương ứng với một bản đồ.

Đầu ra là bản đồ cầu chì / pháo hoa cho mỗi dòng, sử dụng các ký hiệu |-để hiển thị cầu chì và các chữ cái để hiển thị pháo hoa.

Một -cầu chì kết nối với cầu chì và pháo hoa trực tiếp trái / phải của nó, trong khi một |connect cầu chì với những / trên dưới đây. Ví dụ, cầu chì ||được không kết nối và -| .

Ví dụ, hai câu trả lời có thể có ở trên là:

---a        ---------f
  |         |||   ||
  |-c       |||   de
--|--d      a||
| b |        |c
f   e        b

Tất cả các bản đồ cầu chì nên bắt đầu với một -ở góc trên bên trái. Đó là điểm mà bạn thắp sáng cầu chì. Mỗi nhân vật của cầu chì mất một giây để đốt cháy. Như bạn có thể thấy, ađạt được trong ba giây trong cả hai sơ đồ, btrong sáu, v.v.

Bây giờ, cả hai bản đồ được cung cấp ở trên đều hợp lệ cho đầu vào đã cho, nhưng một bản đồ rõ ràng hiệu quả hơn. Một bên trái chỉ sử dụng 13 đơn vị cầu chì, trong khi bên phải mất 20 đơn vị.

Cầu chì không cháy qua pháo hoa! Vì vậy, đối với đầu vào a 3 b 5, điều này không hợp lệ:

---a--b

Thử thách

Mục tiêu của bạn là giảm thiểu lượng cầu chì được sử dụng trong tất cả các trường hợp thử nghiệm. Ghi điểm rất đơn giản, tổng số đơn vị cầu chì được sử dụng.

Nếu bạn không thể tạo bản đồ cho trường hợp thử nghiệm, cho dù đó là trường hợp không thể hay không, thì điểm cho trường hợp đó là tổng của tất cả các lần (41 cho ví dụ ở trên).

Trong trường hợp hòa, cách tính điểm được sửa đổi để bản đồ nhỏ gọn nhất giành chiến thắng. Điểm tiebreak là khu vực của khung giới hạn của mỗi bản đồ. Đó là, độ dài của dòng dài nhất nhân với số lượng dòng. Đối với bản đồ "không thể", đây là hình vuông có số lớn nhất (81 cho ví dụ ở trên).

Trong trường hợp các bài nộp ràng buộc cả hai phương pháp cho điểm này, cà vạt sẽ chuyển đến mục nhập / chỉnh sửa trước đó.

Chương trình của bạn phải có tính xác định, cho mục đích xác minh.

Các trường hợp thử nghiệm

Có 250 trường hợp thử nghiệm, nằm ở đây . Mỗi chiếc có từ 4 đến 26 quả pháo hoa. Thời gian cầu chì tối thiểu cho pháo hoa là 3. Pháo hoa trong mỗi trường hợp được "sắp xếp" theo thời gian và chữ cái, nghĩa là bsẽ không bao giờ sáng trước đó a .

Khi đăng bài, vui lòng bao gồm toàn bộ chương trình của bạn, tổng số điểm của bạn và bản đồ kết quả cho (ít nhất) trường hợp thử nghiệm đầu tiên được đưa ra trong tệp:

a 6 b 8 c 11 d 11 e 11 f 11 g 12 h 15 i 18 j 18 k 21 l 23 m 26 n 28 o 28 p 30 q 32 r 33 s 33 t 34 

Có thể tùy ý nhiều pháo hoa đi cùng một lúc?
Ingo Bürk

Về cơ bản, có. Tôi đã không tìm kiếm ví dụ lớn nhất trong trường hợp thử nghiệm của mình, nhưng tôi biết đó là ít nhất bốn. Thời gian giữa hai cầu chì là rand.nextInt(5)%4, vì vậy 40% cơ hội 0và 20% cho mỗi cầu chì 1,2,3.
Geobits

Chỉ là một gợi ý: Tôi sẽ sử dụng '+' cho nơi cầu chì kết nối hoặc thay đổi hướng, điều đó sẽ khiến đồ họa đầu ra IMHO trực quan hơn nhiều!
flawr

@flawr Tôi sẽ cho phép điều đó, miễn là nó được thực hiện theo cách không thay đổi điểm số. Chẳng hạn, -+-thay vì ---không tự động kết nối pháo hoa ở trên / dưới, vẫn phải có một |bên trên / bên dưới để kết nối nó với pháo hoa. -+-ở chỗ -|-là ổn như nó là.
Geobits

Có phải tất cả các trường hợp thử nghiệm có thể giải quyết? Ví dụ: nếu có năm hoặc nhiều pháo hoa sẽ tắt vào lúc 3, tôi không nghĩ bạn có thể lắp tất cả chúng gần đủ để bắt đầu. Tương tự như vậy, bạn có thể phù hợp với tất cả chúng nhưng chúng có thể chặn đường ra bên ngoài để bắn pháo hoa sau này.
Martin Ender

Câu trả lời:


3

C ++

Tổng chiều dài: 9059, Tổng diện tích: 27469, Thất bại: 13.

Lưu ý: Điểm bao gồm các hình phạt thất bại.


Đầu ra mẫu:

a 6 b 8 c 11 d 11 e 11 f 11 g 12 h 15 i 18 j 18 k 21 l 23 m 26 n 28 o 28 p 30 q 32 r 33 s 33 t 34 
------ae  
     | |  
     |---c
     b||-g
      |d| 
      f | 
    i---| 
  k---| h 
   |  j   
   |---m  
   l  | t 
     o-n| 
      |s-r
      |-| 
      p q 
Length: 39, Area: 150.

a 6 b 6 c 6 d 6 e 6 f 6 g 6 h 8 i 9 j 9 k 9 l 12 m 12 n 13 o 14 p 15 q 15 r 15 s 17 t 17 u 17 v 17 w 17 x 20 y 23 z 26 
------a  n|--w 
|d-||---k|-o|  
| g|b  |--m --x
|-|c    ||--r| 
||f     l|-q | 
||--j u--|--s|-
e|-i    |p|  y|
 h      v t  z-
Length: 56, Area: 120.

Đầu ra đầy đủ: http://pastebin.com/raw.php?i=spBUidBV


Không phải bạn chỉ thích giải pháp vũ phu sao? Đây là nhiều hơn một thuật toán quay lui đơn giản: công nhân không mệt mỏi của chúng tôi di chuyển xung quanh bản đồ, đặt cầu chì và pháo hoa khi cần thiết, trong khi thử nghiệm tất cả các di chuyển có thể tại bất kỳ điểm nào. Chà, gần như --- chúng tôi hạn chế tập hợp các bước di chuyển và từ bỏ các trạng thái không tối ưu sớm để nó không mất nhiều thời gian (và đặc biệt, để nó chấm dứt.) Đặc biệt cẩn thận không tạo ra bất kỳ chu kỳ hoặc ngoài ý muốn những con đường và không quay trở lại giống như cách chúng tôi đã đến, vì vậy, đảm bảo rằng chúng tôi không truy cập cùng một trạng thái hai lần. Mặc dù vậy, việc tìm kiếm một giải pháp tối ưu có thể mất một thời gian, vì vậy cuối cùng chúng tôi từ bỏ việc tối ưu hóa một giải pháp nếu mất quá nhiều thời gian.

Thuật toán này vẫn có một số khoảng trống. Đối với một điều, các giải pháp tốt hơn có thể được tìm thấy bằng cách tăng các FRUSTRATIONtham số. Không có ATM cạnh tranh nhưng những con số này có thể được điều chỉnh nếu và khi ...

Biên dịch với : g++ fireworks.cpp -ofireworks -std=c++11 -pthread -O3.

Chạy với : ./fireworks.

Đọc đầu vào từ STDIN và ghi đầu ra vào STDOUT (có thể không theo thứ tự.)

/* Magic numbers */
#define THREAD_COUNT 2
/* When FRUSTRATION_MOVES moves have passed since the last solution was found,
 * the last (1-FRUSTRATION_STATES_BACKOFF)*100% of the backtracking states are
 * discarded and FRUSTRATION_MOVES is multiplied by FRUSTRATION_MOVES_BACKOFF.
 * The lower these values are, the faster the algorithm is going to give up on
 * searching for better solutions. */
#define FRUSTRATION_MOVES 1000000
#define FRUSTRATION_MOVES_BACKOFF 0.8
#define FRUSTRATION_STATES_BACKOFF 0.5

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <thread>
#include <mutex>
#include <string>
#include <sstream>
#include <cassert>

using namespace std;

/* A tile on the board. Either a fuse, a firework, an empty tile or an
 * out-of-boudns tile. */
struct tile {
    /* The tile's value, encoded the "obvious" way (i.e. '-', '|', 'a', etc.)
     * Empty tiles are encoded as '\0' and OOB tiles as '*'. */
    char value;
    /* For fuse tiles, the time at which the fuse is lit. */
    int time;

    operator char&() { return value; }
    operator const char&() const { return value; }

    bool is_fuse() const { return value == '-' || value == '|'; }
    /* A tile is vacant if it's empty or OOB. */
    bool is_vacant() const { return !value || value == '*'; }

    /* Prints the tile. */
    template <typename C, typename T>
    friend basic_ostream<C, T>& operator<<(basic_ostream<C, T>& os,
                                            const tile& t) {
        return os << (t.value ? t.value : ' ');
    }
};
/* Fireworks have the same encoding as tiles. */
typedef tile firework;
typedef vector<firework> fireworks;

/* The fuse map. It has physical dimensions (its bounding-box) but is
 * conceptually infinite (filled with empty tiles.) */
class board {
    /* The tiles, ordered left-to-right top-to-bottom. */
    vector<tile> p_data;
    /* The board dimensions. */
    int p_width, p_height;
    /* The total fuse length. */
    int p_length;

public:
    board(): p_width(0), p_height(0), p_length(0) {}

    /* Physical dimensions. */
    int width() const { return p_width; }
    int height() const { return p_height; }
    int area() const { return width() * height(); }
    /* Total fuse length. */
    int length() const { return p_length; }

    /* Returns the tile at (x, y). If x or y are negative, returns an OOB
     * tile. */
    tile get(int x, int y) const {
        if (x < 0 || y < 0)
            return {'*'};
        else if (x >= width() || y >= height())
            return {'\0'};
        else
            return p_data[y * width() + x];
    }
    /* Sets the tile at (x, y). x and y must be nonnegative and the tile at
     * (x, y) must be empty. */
    board& set(int x, int y, const tile& t) & {
        assert(x >= 0 && y >= 0);
        assert(!get(x, y));
        if (x >= width() || y >= height()) {
            int new_width = x >= width() ? x + 1 : width();
            int new_height = y >= height() ? y + 1 : height();
            vector<tile> temp(new_width * new_height, {'\0'});
            for (int l = 0; l < height(); ++l)
                copy(
                    p_data.begin() + l * width(),
                    p_data.begin() + (l + 1) * width(),
                    temp.begin() + l * new_width
                );
            p_data.swap(temp);
            p_width = new_width;
            p_height = new_height;
        }
        p_data[y * width() + x] = t;
        if (t.is_fuse())
            ++p_length;
        return *this;
    }
    board&& set(int x, int y, const tile& t) && { return move(set(x, y, t)); }

    /* Prints the board. */
    template <typename C, typename T>
    friend basic_ostream<C, T>& operator<<(basic_ostream<C, T>& os,
                                            const board& b) {
        for (int y = 0; y < b.height(); ++y) {
            for (int x = 0; x < b.width(); ++x)
                os << b.get(x, y);
            os << endl;
        }
        return os;
    }
};

/* A state of the tiling algorithm. */
struct state {
    /* The current board. */
    board b;
    /* The next firework to tile. */
    fireworks::const_iterator fw;
    /* The current location. */
    int x, y;
    /* The current movement direction. 'N'orth 'S'outh 'E'ast, 'W'est or
     * 'A'ny. */
    char dir;
};

/* Adds a state to the state-stack if its total fuse length and bounding-box
 * area are not worse than the current best ones. */
void add_state(vector<state>& states, int max_length, int max_area,
                state&& new_s) {
    if (new_s.b.length() < max_length ||
        (new_s.b.length() == max_length && new_s.b.area() <= max_area)
    )
        states.push_back(move(new_s));
}
/* Adds the state after moving in a given direction, if it's a valid move. */
void add_movement(vector<state>& states, int max_length, int max_area,
                    const state& s, char dir) {
    int x = s.x, y = s.y;
    char parallel_fuse;
    switch (dir) {
    case 'E': if (s.dir == 'W') return; ++x; parallel_fuse = '|'; break;
    case 'W': if (s.dir == 'E') return; --x; parallel_fuse = '|'; break;
    case 'S': if (s.dir == 'N') return; ++y; parallel_fuse = '-'; break;
    case 'N': if (s.dir == 'S') return; --y; parallel_fuse = '-'; break;
    }
    const tile t = s.b.get(s.x, s.y), nt = s.b.get(x, y);
    assert(t.is_fuse());
    if (nt.is_fuse() && !(t == parallel_fuse && nt == parallel_fuse))
        add_state(states, max_length, max_area, {s.b, s.fw, x, y, dir});
}
/* Adds the state after moving in a given direction and tiling a fuse, if it's a
 * valid move. */
void add_fuse(vector<state>& states, int max_length, int max_area,
                const state& s, char dir, char fuse) {
    int x = s.x, y = s.y;
    int sgn;
    bool horz;
    switch (dir) {
    case 'E': ++x; sgn = 1; horz = true; break;
    case 'W': --x; sgn = -1; horz = true; break;
    case 'S': ++y; sgn = 1; horz = false; break;
    case 'N': --y; sgn = -1; horz = false; break;
    }
    if (s.b.get(x, y))
        /* Tile is not empty. */
        return;
    /* Make sure we don't create cycles or reconnect a firework. */
    const tile t = s.b.get(s.x, s.y);
    assert(t.is_fuse());
    if (t == '-') {
        if (horz) {
            if (fuse == '-') {
                if (!s.b.get(x + sgn, y).is_vacant() ||
                    s.b.get(x, y - 1) == '|' ||
                    s.b.get(x, y + 1) == '|')
                    return;
            } else {
                if (s.b.get(x + sgn, y) == '-' ||
                    !s.b.get(x, y - 1).is_vacant() ||
                    !s.b.get(x, y + 1).is_vacant())
                    return;
            }
        } else {
            if (!s.b.get(x, y + sgn).is_vacant() ||
                s.b.get(x - 1, y) == '-' ||
                s.b.get(x + 1, y) == '-')
                return;
        }
    } else {
        if (!horz) {
            if (fuse == '|') {
                if (!s.b.get(x, y + sgn).is_vacant() ||
                    s.b.get(x - 1, y) == '-' ||
                    s.b.get(x + 1, y) == '-')
                    return;
            } else {
                if (s.b.get(x, y + sgn) == '|' ||
                    !s.b.get(x - 1, y).is_vacant() ||
                    !s.b.get(x + 1, y).is_vacant())
                    return;
            }
        } else {
            if (!s.b.get(x + sgn, y).is_vacant() ||
                s.b.get(x, y - 1) == '|' ||
                s.b.get(x, y + 1) == '|')
                return;
        }
    }
    /* Ok. */
    add_state(
        states,
        max_length,
        max_area,
        {board(s.b).set(x, y, {fuse, t.time + 1}), s.fw, x, y, dir}
    );
}
/* Adds the state after adding a firework at the given direction, if it's a
 * valid move. */
void add_firework(vector<state>& states, int max_length, int max_area,
                    const state& s, char dir) {
    int x = s.x, y = s.y;
    int sgn;
    bool horz;
    switch (dir) {
    case 'E': ++x; sgn = 1; horz = true; break;
    case 'W': --x; sgn = -1; horz = true; break;
    case 'S': ++y; sgn = 1; horz = false; break;
    case 'N': --y; sgn = -1; horz = false; break;
    }
    if (s.b.get(x, y))
        /* Tile is not empty. */
        return;
    /* Make sure we don't run into an undeliberate fuse. */
    if (horz) {
        if (s.b.get(x + sgn, y) == '-' || s.b.get(x, y - 1) == '|' ||
            s.b.get(x, y + 1) == '|')
            return;
    } else {
        if (s.b.get(x, y + sgn) == '|' || s.b.get(x - 1, y) == '-' ||
            s.b.get(x + 1, y) == '-')
            return;
    }
    /* Ok. */
    add_state(
        states,
        max_length,
        max_area,
        /* After adding a firework, we can move in any direction. */
        {board(s.b).set(x, y, {*s.fw}), s.fw + 1, s.x, s.y, 'A'}
    );
}
void add_possible_moves(vector<state>& states, int max_length, int max_area,
                        const state& s) {
    /* We add the new states in reverse-desirability order. The most
     * (aesthetically) desirable states are added last. */

    const tile t = s.b.get(s.x, s.y);
    assert(t.is_fuse());

    /* Move in all (possible) directions. */
    for (char dir : "WENS")
        if (dir) add_movement(states, max_length, max_area, s, dir);

    /* If the fuse is too short for the next firework, keep adding fuse. */
    if (t.time < s.fw->time) {
        if (t == '-') {
            add_fuse(states, max_length, max_area, s, 'N', '|');
            add_fuse(states, max_length, max_area, s, 'S', '|');
            add_fuse(states, max_length, max_area, s, 'W', '|');
            add_fuse(states, max_length, max_area, s, 'W', '-');
            add_fuse(states, max_length, max_area, s, 'E', '|');
            add_fuse(states, max_length, max_area, s, 'E', '-');
        } else {
            add_fuse(states, max_length, max_area, s, 'W', '-');
            add_fuse(states, max_length, max_area, s, 'E', '-');
            add_fuse(states, max_length, max_area, s, 'N', '-');
            add_fuse(states, max_length, max_area, s, 'N', '|');
            add_fuse(states, max_length, max_area, s, 'S', '-');
            add_fuse(states, max_length, max_area, s, 'S', '|');
        }
    } else if (t.time == s.fw->time) {
        /* If we have enough fuse for the next firework, place the firework (if
         * possible) and don't add more fuse, or else we'll never finish... */
        if (t == '-') {
            add_firework(states, max_length, max_area, s, 'W');
            add_firework(states, max_length, max_area, s, 'E');
        } else {
            add_firework(states, max_length, max_area, s, 'N');
            add_firework(states, max_length, max_area, s, 'S');
        }
    }
}

void thread_proc(mutex& lock, int& total_length, int& total_area,
                    int& failures) {
    fireworks fw;
    vector<state> states;

    while (true) {
        /* Read input. */
        string input;
        {
            lock_guard<mutex> lg(lock);

            while (!cin.eof() && input.empty())
                getline(cin, input);
            if (input.empty())
                break;
        }
        fw.clear();
        int length = 0, area;
        {
            stringstream is;
            is << input;
            while (!is.eof()) {
                char c;
                int t;
                if (is >> c >> t) {
                    /* Fireworks must be sorted by launch time. */
                    assert(fw.empty() || t >= fw.back().time);
                    fw.push_back({c, t});
                    length += t;
                }
            }
            assert(!fw.empty());
            area = fw.back().time * fw.back().time;
        }

        /* Add initial state. */
        states.push_back({board().set(0, 0, {'-', 1}), fw.begin(), 0, 0, 'A'});

        board solution;
        int moves = 0;
        int frustration_moves = FRUSTRATION_MOVES;

        while (!states.empty()) {
            /* Check for solutions (all fireworks consumed.) */
            while (!states.empty() && states.back().fw == fw.end()) {
                state& s = states.back();
                /* Did we find a better solution? */
                if (solution.area() == 0 || s.b.length() < length ||
                    (s.b.length() == length && s.b.area() < area)
                ) {
                    solution = move(s.b);
                    moves = 0;
                    length = solution.length();
                    area = solution.area();
                }
                states.pop_back();
            }

            /* Expand the top state. */
            if (!states.empty()) {
                state s = move(states.back());
                states.pop_back();
                add_possible_moves(states, length, area, s);
            }

            /* Getting frustrated? */
            ++moves;
            if (moves > frustration_moves) {
                /* Get rid of some data. */
                states.erase(
                    states.begin() + states.size() * FRUSTRATION_STATES_BACKOFF,
                    states.end()
                );
                frustration_moves *= FRUSTRATION_MOVES_BACKOFF;
                moves = 0;
            }
        }

        /* Print solution. */
        {
            lock_guard<mutex> lg(lock);

            cout << input << endl;

            if (solution.area())
                cout << solution;
            else {
                cout << "FAILED!" << endl;
                ++failures;
            }

            cout << "Length: " << length <<
                    ", Area: " << area <<
                    "." << endl << endl;
            total_length += length;
            total_area += area;
        }
    }
}

int main(int argc, const char* argv[]) {
    thread threads[THREAD_COUNT];
    mutex lock;
    int total_length = 0, total_area = 0, failures = 0;

    for (int i = 0; i < THREAD_COUNT; ++i)
        threads[i] = thread(thread_proc, ref(lock), ref(total_length),
                            ref(total_area), ref(failures));
    for (int i = 0; i < THREAD_COUNT; ++i)
        threads[i].join();

    cout << "Total Length: " << total_length <<
            ", Total Area: " << total_area <<
            ", Failures: " << failures <<
            "." << endl;
}

Con trăn

Tổng chiều dài: 17387, Tổng diện tích: 62285, Thất bại: 44.


Đầu ra mẫu:

a 6 b 8 c 11 d 11 e 11 f 11 g 12 h 15 i 18 j 18 k 21 l 23 m 26 n 28 o 28 p 30 q 32 r 33 s 33 t 34
------a                
     |----f            
     |---c             
     b|||---h          
      |dg  |           
      e    |-j         
           |---k       
           i  |        
              |---m    
              l  |-o   
                 |--p  
                 n |--s
                   |-r 
                   q|  
                    t  
Length: 45, Area: 345.

Đầu ra đầy đủ: http://pastebin.com/raw.php?i=mgiqXCRK


Để tham khảo, đây là một cách tiếp cận đơn giản hơn nhiều. Nó cố gắng kết nối pháo hoa với một đường cầu chì chính duy nhất, tạo ra hình dạng "cầu thang". Nếu pháo hoa không thể kết nối trực tiếp với đường chính (xảy ra khi hai hoặc nhiều ánh sáng pháo hoa cùng một lúc), nó sẽ quay trở lại đường chính tìm kiếm một điểm mà nó có thể phân nhánh vuông góc xuống hoặc sang phải (và thất bại nếu không có điểm nào như vậy tồn tại.)

Không có gì đáng ngạc nhiên, nó còn tệ hơn cả người giải quyết vũ phu, nhưng không phải là một lợi thế lớn . Thành thật mà nói, tôi mong đợi sự khác biệt sẽ lớn hơn một chút.

Chạy với : python fireworks.py.

from __future__ import print_function
import sys

total_length = total_area = failures = 0

for line in sys.stdin:
    # Read input.
    line = line.strip()
    if line == "": continue
    fws = line.split(' ')
    # The fireworks are a list of pairs of the form (<letter>, <time>).
    fws = [(fws[i], int(fws[i + 1])) for i in xrange(0, len(fws), 2)]

    # The board is a dictionary of the form <coord>: <tile>.
    # The first tile marks the "starting point" and is out-of-bounds.
    board = {(-1, 0): '*'}
    # The tip of the main "staircase" fuse.
    tip_x, tip_y = -1, 0
    tip_time = 0
    # We didn't fail. Yet...
    failed = False

    for (fw, fw_time) in fws:
        dt = fw_time - tip_time
        # Can we add the firework to the main fuse line?
        if dt > 0:
            # We can. Alternate the direction to create a "staircase" pattern.
            if board[(tip_x, tip_y)] == '-':    dx, dy = 0, 1; fuse = '|'
            else:                               dx, dy = 1, 0; fuse = '-'
            x, y = tip_x, tip_y
            tip_x += dt * dx
            tip_y += dt * dy
            tip_time += dt
        else:
            # We can't. Trace the main fuse back until we find a point where we
            # can thread, or fail if we reach the starting point.
            x, y = tip_x, tip_y
            while board[(x, y)] != '*':
                horz = board[(x, y)] == '-'
                if horz:    dx, dy = 0, 1; fuse = '|'
                else:       dx, dy = 1, 0; fuse = '-'
                if dt > 0 and (x + dx, y + dy) not in board: break
                if horz:    x -= 1
                else:       y -= 1
                dt += 1
            if board[(x, y)] == '*':
                failed = True
                break
        # Add the fuse and firework.
        for i in xrange(dt):
            x += dx; y += dy
            board[(x, y)] = fuse
        board[(x + dx, y + dy)] = fw

    # Print output.
    print(line)
    if not failed:
        max_x, max_y = (max(board, key=lambda p: p[i])[i] + 1 for i in (0, 1))
        for y in xrange(max_y):
            for x in xrange(max_x):
                print(board.get((x, y), ' '), end = "")
            print()
        length = len(board) - len(fws) - 1
        area = max_x * max_y
    else:
        print("FAILED!")
        failures += 1
        length = sum(map(lambda fw: fw[1], fws))
        area = fws[-1][1] ** 2
    print("Length: %d, Area: %d.\n" % (length, area))
    total_length += length; total_area += area

print("Total Length: %d, Total Area: %d, Failures: %d." %
        (total_length, total_area, failures))

Vì tò mò, việc này mất bao lâu để hoàn thành với các tham số hiện tại?
Geobits

@Geobits: Rõ ràng là nó phụ thuộc vào máy móc, và tôi đã không theo dõi quá chặt chẽ, nhưng tôi nghĩ khoảng hai mươi phút, cho hoặc nhận.
DarwinBot
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.