ทำบิตทวีป


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

เราต้องการตั้งค่าบิตบางส่วนในเมทริกซ์นี้ซึ่งมันจะก่อตัวเป็นหยดติดกันของ1s โดยที่ทุก ๆ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-ยากก็ไม่ได้เป็นปัญหาที่ดีสำหรับการเร็วที่สุดอัลกอริทึม
ปีเตอร์เทย์เลอร์

1
@Peter Taylor และ esolangingfruit NP-Hardness
FantaC

1
ในแง่ของปีเตอร์เทย์เลอร์และแสดงความคิดเห็น HyperNeutrino และความจริงที่ว่าคำถามที่ขณะนี้มีคำตอบไม่ฉันเปลี่ยนวิธีการให้คะแนนเพื่อรหัสกอล์ฟ
แยกผลไม้

1
เราควรทำอย่างไรถ้าไม่มี1เมทริกซ์?
Colera Su

คำตอบ:


1

C (gcc), 308 306 ไบต์

ฟังก์ชั่นfได้รับ(height, width, flattened array, pointer to ans)และส่งกลับคำตอบโดยตัวชี้

ถ้าไม่มีในเมทริกซ์ก็จะกลับ10

#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;}

ลองออนไลน์!

Ungolfed:

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 ไบต์

โปรแกรมเต็มรูปแบบที่ใช้รายการของรายการผ่านอินพุตของผู้ใช้ ฟังก์ชั่นIและdนับจำนวนเกาะในอาร์เรย์ สำหรับวงที่ระบุในตอนท้ายผ่านไปได้ทั้งหมดที่คุณสามารถเปลี่ยน0เพื่อ1s แล้วถ้ามีเป็นเกาะหนึ่งในร้านค้าที่เหลือจำนวน1s 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)

ลองออนไลน์!

Pregolfed version ก่อนที่ฉันจะปรับปรุงบางสิ่ง:

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.