비트 대륙 만들기


11

비트 행렬 (최소 하나 이상 포함)이 있다고 가정 해 봅시다 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

이 행렬에서 비트의 일부를 설정하여 연속적인 블로 브를 형성합니다 1. 여기서 모든 비트는 직교 이동을 통해 1서로 직접 또는 간접적으로 연결됩니다 1.

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

( 1브라우저의 "찾기"기능 으로 검색하면 더 명확하게 볼 수 있습니다 .)

그러나 설정 한 비트 수를 최소화하려고합니다.

작업

비트 또는 부울의 행렬 (또는 배열의 배열)이 주어지면 연속적인 1s 대륙을 만들기 위해 설정해야하는 최소 비트 수를 반환합니다 . 직교 방향으로 다른 세트 비트로 만 이동하여 매트릭스의 한 세트 비트에서 다른 세트 비트로 이동할 수 있어야합니다.

이것은 이므로 가장 짧은 유효한 제출 (바이트 단위로 측정)이 이깁니다.

테스트 사례

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
좀 더 설명이 필요합니다. 매트릭스에서 "연속 블롭"이란 무엇입니까?
NoOneIsHere 여기

11
문제는 NP-hard알려져 있기 때문에 가장 빠른 알고리즘 에는 좋은 문제가 아닙니다 .
피터 테일러

1
@ 피터 테일러와 esolangingfruit NP-경도
FantaC

1
Peter Taylor와 HyperNeutrino의 의견과 현재 질문에 대한 답변이 없다는 사실을 감안하여 점수 방법을 code-golf 로 변경하고 있습니다.
Esolanging Fruit

1
1행렬 이 없으면 어떻게해야 합니까?
Colera Su

답변:


1

C (gcc), 308306 바이트

함수 f는를 받고 (height, width, flattened array, pointer to ans)포인터로 응답을 반환합니다.

더 있다면 1매트릭스, 그것은 반환하지 않습니다 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;}

온라인으로 사용해보십시오!

언 골프 드 :

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

파이썬 2 , 611 바이트

사용자 입력을 통해 목록 목록을 가져 오는 전체 프로그램입니다. 기능 Id배열에 도수를 카운트. 끝에있는 for 루프는 0s를 1s로 변경할 수있는 모든 가능성을 열거 한 다음 하나의 섬이 남아 있으면 1목록에 추가 된 s 의 수를 저장 합니다 C. 이 목록의 최소값은 모든 섬을 연결하는 데 필요한 최소 비트 플립 수입니다. 매우 느린 알고리즘이므로 60 대 미만의 테스트 사례를 실행하지 않지만 (더 오래 시도하지 않았지만) 더 작은 (~ 5x5) 테스트 사례를 시도했는데 제대로 작동하는 것 같습니다. 페이지 에서 섬 계산 알고리즘을 얻었습니다 .

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)

온라인으로 사용해보십시오!

몇 가지 사항을 최적화하기 전 사전 골프 버전 :

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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.