Tạo một lục địa bit


11

Hãy tưởng tượng chúng ta có một ma trận các bit (chứa ít nhất một 1):

0 1 0 1 1 0 1 0 0 1 0
0 1 0 1 0 0 1 0 1 1 0
0 0 1 0 1 1 0 1 0 1 0
1 1 0 0 1 0 0 1 1 0 1
0 0 0 1 0 1 1 0 0 1 0

Chúng tôi muốn thiết lập một số bit trong ma trận này sao cho nó tạo thành một đốm liền kề của 1s, trong đó mọi bit 1được kết nối trực tiếp hoặc gián tiếp với nhau 1thông qua chuyển động trực giao:

0 1 1 1 1 1 1 0 0 1 0
0 1 0 1 0 0 1 0 1 1 0
0 1 1 0 1 1 1 1 0 1 0
1 1 0 0 1 0 0 1 1 1 1
0 0 0 1 1 1 1 0 0 1 0

(Bạn có thể thấy rõ hơn điều này bằng cách tìm kiếm 1với tính năng "tìm" của trình duyệt.)

Tuy nhiên, chúng tôi cũng muốn giảm thiểu số lượng bit mà chúng tôi đặt.

Nhiệm vụ

Đưa ra một ma trận (hoặc mảng các mảng) của bit hoặc booleans, trả về số lượng bit tối thiểu cần được đặt để tạo ra một lục địa liền kề của 1s. Có thể lấy từ bit set này trong ma trận sang ma trận khác bằng cách chỉ di chuyển theo hướng trực giao với các bit set khác.

Đây là , vì vậy bài nộp hợp lệ ngắn nhất (tính bằng byte) sẽ thắng.

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

0 1 0 1 1 0 1 0 0 1 0
0 1 0 1 0 0 1 0 1 1 0
0 0 1 0 1 1 0 1 0 1 0
1 1 0 0 1 0 0 1 1 0 1
0 0 0 1 0 1 1 0 0 1 0
=> 6

1 0 0 0 0 0 1 0 0
1 1 0 0 1 1 1 0 0
1 1 1 0 1 1 1 1 1
0 1 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 1
0 1 0 0 0 0 1 1 0
1 0 0 0 0 0 1 0 0
=> 4

0 0 0 1 1 1 0 1 1
0 0 1 0 0 0 0 1 0
0 0 1 1 1 1 1 1 0
1 1 0 0 1 1 0 0 0
0 0 1 1 1 0 0 1 1
0 1 1 1 0 0 0 0 0
1 1 1 0 0 1 1 1 0
1 1 1 0 1 1 0 1 1
0 0 0 0 1 0 0 0 1
1 1 0 0 1 1 0 1 1
0 0 0 0 0 0 0 1 0
0 1 1 1 1 0 0 0 0
0 0 0 1 1 0 0 0 1
0 1 0 0 1 0 1 1 0
0 1 1 1 0 0 0 0 1
=> 8

1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
=> 0

1
Điều này cần thêm một chút giải thích. Một "blob liền kề" trong một ma trận là gì?
NoOneIsHãy là

11
Vì vấn đề được biết đến là NP-hard nên nó không phải là vấn đề tốt đối với thuật toán nhanh nhất .
Peter Taylor

1
@Peter Taylor và esolangingfruit NP-Hardness
FantaC

1
Theo ý kiến ​​của Peter Taylor và HyperNeutrino, và thực tế là câu hỏi hiện không có câu trả lời, tôi đang thay đổi phương pháp tính điểm thành môn đánh gôn .
Esolanging Fruit 12/12/17

1
Chúng ta nên làm gì nếu không có 1trong ma trận?
Colera Su

Câu trả lời:


1

C (gcc), 308 306 byte

Hàm fnhận (height, width, flattened array, pointer to ans)và trả về câu trả lời bằng con trỏ.

Nếu không có 1trong ma trận, nó sẽ trở lại 0.

#define v A[i]
N,M,K,R,C,T,i,*A;s(x,y){i=x*M+y;if(!(x<0|y<0|x>=N|y>=M|v^1))v=2,s(x,y+1),s(x,y-1),s(x+1,y),s(x-1,y);}g(i){if(C<R){if(i^K){g(i+1);if(!v)C+=v=1,g(i+1),v=0,C--;}else{T=1;for(i=0;i<K&&!v;i++);s(i/M,i%M);for(i=0;i<K;i++)T&=v^1,v=!!v;if(T)R=C;}}}f(n,m,a,b)int*a,*b;{K=R=(N=n)*(M=m),A=a;g(0);*b=R;}

Hãy thử trực tuyến!

Ung dung:

N,M,R,C,T,i,*A; // height, width, result, recursion depth

s(x,y)
{ // depth first search: replace all 1 in the same connected component with 2
    i=x*M+y;
    if(!(x<0|y<0|x>=N|y>=M|A[i]^1)) { // check if out of boundary
        A[i]=2;
        s(x, y+1),s(x, y-1),s(x+1, y),s(x-1, y);
    }
}

g(i)
{ // enumerate all posible solutions
    if(C<R) {
        if(i!=N*M) {
            g(i+1);      // nothing change for this entry
            if (!A[i]) { // set the entry to 1
                C++, A[i]=1;
                g(i+1);
                C--, A[i]=0;
            }
        }
        else {
            T=1;
            for (i=0; i<N*M && !A[i]; i++); // find first non-zero entry
            s(i/M, i%M);     // replace the connected component
            for (i=0; i<N*M; i++) {
                T&=A[i]!=1;   // check if no other components
                A[i]=!!A[i]; // change 2s back to 1
            }
            if (T) R=C;      // update answer
        }
    }
}

f(n,m,a,b)int*a,*b;{
    R=(N=n)*(M=m), A=a;
    g(0);
    *b=R;
}

0

Python 2 , 611 byte

Một chương trình đầy đủ có một danh sách các danh sách thông qua đầu vào của người dùng. Các chức năng Idđếm số lượng đảo trong mảng. Vòng lặp for ở cuối liệt kê thông qua tất cả các khả năng nơi bạn có thể thay đổi 0s thành 1s sau đó nếu có một đảo còn lại lưu số 1s được thêm vào danh sách C. Tối thiểu của danh sách đó là số lần lật bit tối thiểu cần thiết để kết nối bất kỳ đảo nào. Đây là một thuật toán rất chậm nên nó không chạy các trường hợp thử nghiệm được đưa ra trong độ tuổi dưới 60 (tôi đã không thử lâu hơn) nhưng tôi đã thử một vài trường hợp thử nghiệm nhỏ hơn (~ 5x5) và nó dường như hoạt động chính xác. Tôi có thuật toán đảo đếm từ này trang.

from itertools import*
def d(g,i,j,v):
 v[i][j],R,C=1,[-1,1,0,0],[0,0,-1,1]
 for k in range(4):
	if len(g)>i+R[k]>=0<=j+C[k]<len(g[0]):
	 if v[i+R[k]][j+C[k]]<1and g[i+R[k]][j+C[k]]:v=d(g,i+R[k],j+C[k],v)
 return v
def I(g):
 w=len(g[0])
 v,c=[w*[0]for r in g],0
 for i in range(len(g)*w):
	if v[i/w][i%w]<1and g[i/w][i%w]>0:v=d(g,i/w,i%w,v);c+=1
 return c           
g=input()
C=[]
for p in [list(t)for t in product([0,1],repeat=sum(r.count(0)for r in g))]:
 h,G,x=0,[r[:]for r in g],len(g[0])
 for i in range(x*len(G)):
	if G[i/x][i%x]<1:h+=p[0];G[i/x][i%x]=p[0];del p[0]
 if I(G)<2:
	C.append(h)
print min(C)

Hãy thử trực tuyến!

Phiên bản Pregolfed trước khi tôi tối ưu hóa một số điều:

from itertools import*
def d(g,i,j,v):
    v[i][j]=1
    R=[-1,1,0,0]
    C=[0,0,-1,1]
    for k in range(4):
        if len(g)>i+R[k]>=0<=j+C[k]<len(g[0]):
            if v[i+R[k]][j+C[k]]<1:
                if g[i+R[k]][j+C[k]]:
                    v=d(g,i+R[k],j+C[k],v)
    return v
def I(g):
    w=len(g[0])
    v=[[0]*w for r in g]
    c=0
    for i in range(len(g)):
        for j in range(w):
            if v[i][j]<1and g[i][j]>0:
                v=d(g,i,j,v)
                c+=1
    return c           
g=input()
z=sum(r.count(0)for r in g)
f=[list(t)for t in product('01',repeat=z)]
C=[]
for p in f:
    h=0
    G=[r[:]for r in g]
    x=len(G[0])
    for i in range(x*len(G)):
        exec('h+=int(p[0]);G[i/x][i%x]=int(p[0]);del p[0]'*(G[i/x][i%x]<1))
    if I(G)<2:
        C.append(h)
print min(C)
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.