Trường hợp xấu nhất Manhattan Loại trừ


20

Hãy tưởng tượng một lưới hình vuông W bằng H bao bọc hình xuyến. Các mục được đặt trên lưới như sau.

Mục đầu tiên có thể được đặt trên bất kỳ vuông, nhưng mục tiếp theo không phải nằm trong một khoảng cách Manhattan R của bất kỳ mục trước (còn được gọi là một khu phố Von Neumann phạm vi R ). Lựa chọn cẩn thận các vị trí cho phép lắp một số lượng lớn các mục vào lưới trước khi không có vị trí hợp lệ hơn. Tuy nhiên, thay vào đó hãy xem xét mục đích ngược lại: số lượng vật phẩm thấp nhất có thể được đặt và không để lại vị trí hợp lệ nào nữa?

Đây là vùng loại trừ bán kính 5:

Vùng loại trừ bán kính 5

Đây là một khu vực loại trừ bán kính 5 khác, lần này là gần các cạnh nên hành vi bao bọc là rõ ràng:

Bao bọc bán kính 5 vùng loại trừ

Đầu vào

Ba số nguyên:

  • W : chiều rộng của lưới (số nguyên dương)
  • H : chiều cao của lưới (số nguyên dương)
  • R : bán kính của vùng loại trừ (số nguyên không âm)

Đầu ra

Một số nguyên N , là số lượng nhỏ nhất của các mục có thể được đặt ngăn chặn mọi vị trí hợp lệ hơn nữa.

Chi tiết

  • Bán kính bằng 0 cho vùng loại trừ 1 ô vuông (một ô được đặt trên đó).
  • Bán kính N không bao gồm vùng có thể đạt được trong N bước trực giao (nhớ các cạnh được bao bọc theo hình xuyến).

Mã của bạn phải hoạt động trong trường hợp tầm thường R = 0, nhưng không cần làm việc cho W = 0 hoặc H = 0.

Mã của bạn cũng phải xử lý trong trường hợp R > W hoặc R > H .

Giới hạn thời gian và trường hợp kiểm tra

Mã của bạn phải có khả năng xử lý tất cả các trường hợp thử nghiệm và mỗi trường hợp thử nghiệm phải hoàn thành trong vòng 5 phút. Điều này sẽ dễ dàng (ví dụ giải pháp JavaScript mất vài giây cho mỗi trường hợp thử nghiệm). Giới hạn thời gian chủ yếu là để loại trừ phương pháp vũ phu cực đoan. Cách tiếp cận ví dụ vẫn còn khá mạnh mẽ.

Nếu mã của bạn hoàn thành trong vòng 5 phút trên một máy nhưng không phải trên máy khác sẽ đủ gần.

Các trường hợp thử nghiệm ở dạng đầu vào: đầu ra nhưW H R : N

5 4 4 : 1
5 4 3 : 2
5 4 2 : 2
5 4 1 : 5

7 5 5 : 1
7 5 4 : 2
7 5 3 : 2
7 5 2 : 4

8 8 8 : 1
8 8 7 : 2
8 8 6 : 2
8 8 5 : 2
8 8 4 : 2
8 8 3 : 4

 7  6  4 : 2
 7  6  2 : 4
11  7  4 : 3
11  9  4 : 4
13 13  6 : 3
11 11  5 : 3
15 14  7 : 2
16 16  8 : 2

Đoạn trích để giúp hình dung và chơi xung quanh với các ý tưởng

Giải pháp ví dụ

Chỉ là một ví dụ cho đầu ra nhỏ (kết quả từ bán kính không nhỏ hơn nhiều so với chiều rộng và chiều cao). Có thể xử lý bất kỳ trường hợp thử nghiệm nào nhưng sẽ hết thời gian và bỏ cuộc cho hầu hết các trường hợp lớn hơn.


4
Đoạn mã tuyệt vời!
Căng thẳng điên cuồng

@StretchManiac cảm ơn :) Tôi đang cố gắng học JavaScript để mọi phản hồi đều được chào đón
trichoplax

1
Đó là một đoạn khá hay. Tôi thích cách phối màu đó. Có phải từ một bảng màu?
dặm

@miles cảm ơn bạn - màu sắc chỉ được đoán và sau đó tinh chỉnh một chút (nhưng không nhiều - chúng vẫn là tất cả 3 mã màu ký tự chứ không phải 6). Bạn có thể thấy các màu được sử dụng trong khối dòng thứ ba trong mã đoạn.
trichoplax

Câu trả lời:


5

Python 2, 216 182 byte

def f(W,H,R):L={(i%W,i/W)for i in range(W*H)};M={(x,y)for x,y in L if min(x,W-x)+min(y,H-y)>R};g=lambda s:min([1+g(s-{((a+x)%W,(b+y)%H)for x,y in L-M})for a,b in s]or[1]);return g(M)

Đầu vào như thế nào f(16,16,8). Sử dụng khá nhiều thuật toán giống như mẫu của @ trichoplax , nhưng với các bộ. Ban đầu tôi không đặt mục đầu tiên tại(0, 0) , nhưng điều này khiến nó bị sặc trong vài trường hợp gần đây.

Tất cả các trường hợp trên hoàn thành trong vòng 10 giây, dưới giới hạn. Trong thực tế, các trường hợp đủ nhỏ để tôi có một căn phòng nhỏ để hoạt động kém hiệu quả hơn, cho phép tôi loại bỏ một kiểm tra kiểm tra các trạng thái trùng lặp.

(Cảm ơn @trichoplax đã giúp đỡ chơi gôn)

Mở rộng:

def f(W,H,R):
  # All cells
  L={(i%W,i/W)for i in range(W*H)}                 

  # Mask: Complement of exclusion zone around (0, 0) 
  M={(x,y)for x,y in L if min(x,W-x)+min(y,H-y)>R}

  # Place recursively
  g=lambda s:min([1+g(s-{((a+x)%W,(b+y)%H)for x,y in L-M})for a,b in s]or[1])
  return g(M)

2

Con trăn 3, 270 262 260 251 246 226

(Cảm ơn Sp3000 vì:

  • -~ thay vì +1 , cho phép tôi mất một khoảng trống sau return dòng cuối cùng.
  • mất dấu ngoặc đơn xung quanh W*H .
  • cừu ...
  • đặt mọi thứ trên một dòng
  • python modulo %cho kết quả dương cho số âm, để lưu thêm 20 byte)

Đây là câu trả lời ví dụ JavaScript từ câu hỏi được chuyển sang Python 3.

Để tránh phải vượt qua rất nhiều đối số hàm xung quanh, tôi đã di chuyển hai hàm hỗ trợ bên trong hàm tính toán để chúng chia sẻ phạm vi của nó. Tôi cũng đã cô đọng từng chức năng này thành một dòng duy nhất để tránh chi phí thụt đầu dòng.

Giải trình

Cách tiếp cận khá tàn bạo này đặt vật phẩm đầu tiên vào (0, 0), và sau đó đánh dấu tất cả các ô vuông bị loại trừ. Sau đó, nó đệ quy đặt một mục tại tất cả các ô vuông hợp lệ còn lại cho đến khi tất cả các ô vuông được loại trừ và trả về số lượng tối thiểu của các mục cần thiết.

Mã đánh gôn:

def C(W,H,R):r=range;M=lambda g:min([M(G(g,x,y))for x in r(W)for y in r(H)if g[x+W*y]]or[-1])+1;G=lambda g,x,y:[g[a+W*b]if min((x-a)%W,(a-x)%W)+min((y-b)%H,(b-y)%H)>R else 0for b in r(H)for a in r(W)];return-~M(G([1]*W*H,0,0))

Mã bị đánh cắp:

def calculate(W, H, R):
    starting_min = W * H + 1
    cells = [0] * (W * H)
    grid_state = grid_with_item_added(cells, 0, 0, W, H, R)
    return min_from_here(grid_state, starting_min, W, H, R) + 1

def min_from_here(grid_state, starting_min, W, H, R):
    no_cells = True
    min = starting_min
    for x in range(W):
        for y in range(H):
            if grid_state[x + W * y] == 0:
                no_cells = False
                new_grid_state = grid_with_item_added(grid_state, x, y, W, H, R)
                m = min_from_here(new_grid_state, starting_min, W, H, R)
                if m < min:
                    min = m

    if no_cells:
        return 0
    else:
        return min + 1

def grid_with_item_added(grid_state, x, y, W, H, R):
    grid = grid_state[:]
    for a in range(W):
        for b in range(H):
            if manhattan_distance(a, b, x, y, W, H) <= R:
                grid[a + W * b] = 1

    return grid

def manhattan_distance(a, b, c, d, W, H):
    horizontal = min(abs(W + c - a) % W, abs(W + a - c) % W)
    vertical = min(abs(H + d - b) % H, abs(H + b - d) % H)
    return horizontal + vertical


if __name__ == '__main__':
    import sys
    arguments = sys.argv[1:]
    if len(arguments) < 3:
        print('3 arguments required: width, height and radius')
    else:
        print(calculate(int(arguments[0]), int(arguments[1]), int(arguments[2])))

Mã không xác định định nghĩa một hàm và cũng bao gồm mã để cho phép nó được gọi từ dòng lệnh. Mã golf chỉ xác định chức năng, đủ cho các câu hỏi golf mã tiêu chuẩn .

Nếu bạn muốn kiểm tra mã đánh gôn từ dòng lệnh, thì đây là phần xử lý dòng lệnh đi kèm (nhưng không được đánh gôn):

Dòng lệnh mã có thể kiểm tra

def C(W,H,R):r=range;M=lambda g:min([M(G(g,x,y))for x in r(W)for y in r(H)if g[x+W*y]]or[-1])+1;G=lambda g,x,y:[g[a+W*b]if min((x-a)%W,(a-x)%W)+min((y-b)%H,(b-y)%H)>R else 0for b in r(H)for a in r(W)];return-~M(G([1]*W*H,0,0))

if __name__ == '__main__':
    import sys
    arguments = sys.argv[1:]
    if len(arguments) < 3:
        print('3 arguments required: width, height and radius')
    else:
        print(C(int(arguments[0]), int(arguments[1]), int(arguments[2])))
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.