การจัดเรียงสี่เหลี่ยมโดยพลการเพื่อเติมช่องว่าง


26

สี่เหลี่ยมเหล่านี้สามารถเติมเต็มพื้นที่สี่เหลี่ยมได้หรือไม่?

เมื่อให้รูปสี่เหลี่ยมผืนผ้าคุณจะถูกถามว่าสามารถจัดเรียงให้เต็มพื้นที่สี่เหลี่ยมหรือไม่

รายละเอียด

รับพวงของm x nรูปสี่เหลี่ยมโดยพลการ; 0 <= m, n <= 1000ตรวจสอบว่าเป็นไปได้หรือไม่ที่จะจัดเรียงเพื่อให้ครอบคลุมพื้นที่สี่เหลี่ยมโดยไม่ต้องมีรูหรือทับซ้อนกัน ไม่สามารถหมุนสี่เหลี่ยมได้และแต่ละสี่เหลี่ยมจะวางเพียงครั้งเดียวเท่านั้น

อินพุต

อินพุตสำหรับสิ่งนี้มีความยืดหยุ่นมากตราบใดที่อินพุตให้รายการของมิติพื้นที่ 2 แบบ ตัวอย่างเช่นทั้งสองอย่างต่อไปนี้ถูกต้อง:

คั่นด้วย Space, Return

1 2
1 5
4 5
3 6

รายการขนาด

[[1, 2], [1, 5], [4, 5], [3, 6]]

เอาท์พุต

การเรียงลำดับของค่าจริง / เท็จเช่นจริง / เท็จ, 0/1, T / F, จริง / เท็จ ฯลฯ หากคุณกำลังจะใช้วิธีการแสดงผลที่ไม่ชัดเจนมากโปรดระบุในคำตอบของคุณ

ตัวอย่าง

กรณีทดสอบ 1

การป้อนข้อมูล:

1 1
1 5
2 6

ผลลัพธ์: true(หรือบางอย่างที่คล้ายกัน)
วิธีจัดเรียง:

XYYYYY
ZZZZZZ
ZZZZZZ

กรณีทดสอบ 2

การป้อนข้อมูล:

1 1
2 2

เอาท์พุท: false(หรือบางอย่างที่คล้ายกัน)
คำอธิบาย: เห็นได้ชัดว่าคุณไม่สามารถจัดเรียงสี่เหลี่ยมสองขนาดที่มีขนาดแตกต่างกัน

กรณีทดสอบ 3

การป้อนข้อมูล:

1 1
1 2
1 2
2 1
2 1

ผลลัพธ์: true(หรือบางอย่างที่คล้ายกัน) วิธีจัดเรียง:

AAB
DEB
DCC

ตามที่ @ETHProductions ชี้ให้เห็นสำหรับกรณีทดสอบอื่นทั้งหมดคุณสามารถรวมรูปสี่เหลี่ยมกับความยาวขอบทั่วไปได้จนกว่าคุณจะมีเพียงหนึ่งรูปสี่เหลี่ยมผืนผ้าดังนั้นกรณีทดสอบนี้จึงเป็นการทำลายรหัสใด ๆ ที่ใช้ความคิดนี้

กรณีทดสอบ 4

การป้อนข้อมูล:

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

ผลลัพธ์: true(หรือบางอย่างที่คล้ายกัน)
วิธีจัดเรียง:

AAABBBBEE
AAACCDDDD
FFFFFGGGH
FFFFFGGGH
IIIJJKKLH
IIIMMMMMH

หมายเหตุ : คุณไม่จำเป็นต้องระบุวิธีการจัดเรียงคุณจะต้องพิจารณาว่าไม่สามารถจัดเรียงได้

นี่คือรหัสกอล์ฟดังนั้นคำตอบที่สั้นที่สุดในจำนวนไบต์ชนะ! ฉันจะยอมรับคำตอบที่สั้นที่สุดของวันที่ 14 มกราคม แต่อย่าลังเลที่จะส่งคำตอบในภายหลังกว่านั้นเพราะฉันยังสามารถให้ upvotes ได้! :)

มีความสุขในการเล่นกอล์ฟ!

~ AL

ป.ล. หากคุณทราบว่าควรใช้แท็กใดกับปัญหานี้โปรดเพิ่มฉันไม่ทราบเลยว่าจะใส่แท็กอื่นนอกเหนือจากโค้ดกอล์ฟ

แก้ไข : โปรแกรมของคุณควรสามารถประมวลผลได้ถึง 25 สี่เหลี่ยมในเวลาไม่เกิน 10 วินาทีในคอมพิวเตอร์ที่เหมาะสม (ฉันจะค่อนข้างยืดหยุ่นในกฎนี้)

แก้ไข : ฉันได้ขยายกำหนดเวลาตอบรับการส่งเป็นวันสุดท้ายของปี แต่ฉันสงสัยว่าฉันจะได้รับคำตอบภายใน ...

แก้ไข : ฉันได้ขยายกำหนดเวลาตอบรับการส่งภายใน 2 สัปดาห์ดังนั้นหากไม่มีคำตอบอีกแล้วคำตอบ C ปัจจุบันจะได้รับการยอมรับ! :)


ฉันจะใช้สี่เหลี่ยมอินพุตแต่ละอันใช้เพียงครั้งเดียวหรือไม่
xnor

7
ทำไมถึงมีกำหนดเวลา คุณอาจจะบอกว่าคุณจะยอมรับคำตอบในเวลานั้น แต่ความท้าทายที่ควรจะเปิดไปเรื่อย ๆ :)
นาธานเมอร์

4
สี่เหลี่ยมสามารถหมุนได้หรือไม่?
xnor

3
ดีปัญหาของคุณคือปัญหา decidability: "สามารถจัดเรียงสี่เหลี่ยมที่มุ่งเน้นเหล่านี้เพื่อสร้างสี่เหลี่ยมอีกรูปด้วย 0 ขยะ" ซึ่งเป็นปัญหา NP-complete (Korf, 2003: pdfs.semanticscholar.org/90a5/ … ) อัลกอริธึมของ Korf นั้นเป็นสัตว์เดียรัจฉานที่มีการเพิ่มประสิทธิภาพบางอย่างเพื่อกำจัดการกำหนดค่าได้อย่างมีประสิทธิภาพมากขึ้นโดยไม่มีวิธีแก้ปัญหา ฉันสงสัยว่ากอล์ฟประเภทนี้จะมีอักขระน้อยกว่า 250 ตัวในเกือบทุกภาษา
Gabriel Benamy

1
เส้นทางที่ง่ายคือการพิจารณาว่าคุณสามารถรวมสี่เหลี่ยมสองรูปที่มีความกว้างหรือความสูงเดียวกันซ้ำ ๆ กันหรือไม่จนกว่าคุณจะเหลือ 1 สี่เหลี่ยม อัลกอริธึมนี้ใช้ได้กับการทดสอบปัจจุบันทั้งหมด อย่างไรก็ตามมันล้มเหลวสำหรับ[[1, 2], [2, 1], [1, 1], [1, 2], [2, 1]](ซึ่งสามารถจัดเรียงได้ABB ACD EED) คุณอาจต้องการเพิ่มกรณีทดสอบอย่างง่ายนี้
ETHproductions

คำตอบ:


5

C, 1135 1158 1231 1598ไบต์

มันผ่านเส้นตายที่กำหนดไว้แล้ว แต่เมื่อเห็นว่ายังไม่มีคำตอบนี่เป็นหนึ่ง (ยาวไปหน่อย) ในซี

ผลตอบแทน:

  • 0 (ศูนย์) เมื่อเกิดความล้มเหลว (ไม่พอดี)
  • เมทริกซ์ฟิตติ้งเต็มรูปแบบบนความสำเร็จ

ปรับปรุง:

รหัสดั้งเดิมอาจติดอยู่กับเมทริกซ์บางตัวใช้เวลานานกว่า 10 วินาทีที่อนุญาต การแก้ไขในปัจจุบันควรดำเนินการฝึกอบรมให้เสร็จภายในเวลา 1 วินาที สิ่งนี้สามารถทำได้โดย 1) การเรียงลำดับสี่เหลี่ยมอินพุตและ 2) การข้ามขนาดซ้ำเมื่อทำการติดตั้ง

แข็งแรงเล่นกอล์ฟ:

#define R r[i]
#define Z return
#define _(B,D,E) for(int B=E;B<D;B++)
struct{int x,y,u,p;}r[25],*S;int A,M,N,U,V,X,Y;char *P;T(x,y,w,h){_(I,x+w,x)_(J,y+h,y)if(I/U|J/V|P[J*U+I])Z 0;Z 1;}L(x,y,w,h,c){_(I,x+w,x)_(J,y+h,y)P[J*U+I]=c;}F(){int x=0,y;while(++x<A)if(!P[x])break;if(x/A){_(i,V,0)printf("%*.*s\n",U,U,P+i*U);exit(0);}y=x/U;x-=y*U;_(i,N,0)if(!R.u&T(x,y,R.x,R.y))R.u=1,L(x,y,R.x,R.y,'A'+i),F(),R.u=0,L(x,y,R.x,R.y,0);}O(i,y){if(!R.u){if(!T(0,y,R.x,R.y))Z;R.u=1;R.p=0;L(0,y,R.x,R.y,'A'+i);y+=R.y;}if(y-V||F())_(j,N,0)if(j-i&!r[j].u){O(j,y);while(r[j].x-r[j+1].x|r[j].y-r[j+1].y)j++;}R.u=0;L(R.p,(y-=R.y),R.x,R.y,0);}Q(i,x){if(!R.u){if(R.x>U-x)Z;R.u=1;R.p=x;L(x,0,R.x,R.y,'A'+i);x+=R.x;}if(x-U||O(i,1))_(j,N,0)if(j-i&!r[j].u)Q(j,x);L(x-=R.x,0,R.x,R.y,0);R.u=0;}C(int*a,int*b){Z*a-*b?*a-*b:a[1]-b[1];}main(){_(i,25,0)if(++N&scanf("%d%d\n",&R.x,&R.y)-2)break;_(i,N,0){A+=R.x*R.y;if(R.x>X)X=R.x;if(R.y>Y)Y=R.y;}_(i,A+1,1)if(!(A%i)){if(i<Y|A/i<X)continue;M++;S=realloc(S,M*16);S[M-1].y=i;S[M-1].x=A/i;}qsort(S,M,16,C);P=calloc(A+1,1);_(j,M,0){U=S[j].x;V=S[j].y;_(i,N,0)R.u=1,L(0,0,R.x,R.y,'A'+i),Q(i,R.x),R.u=0;}printf("0\n");exit(1);}

UnGolfed:

#define R r[i]
#define Z return
#define _(B,D,E) for(int B=E;B<D;B++)
struct {
    int x,y,u,p;
} r[25],*S;
int A,M,N,U,V,X,Y;
char *P;

test_space(x,y,w,h) {
    _(I,x+w,x)
        _(J,y+h,y)
            if (    I >= U |
                    J >= V |
                    P[J*U+I]) Z 0;
    Z 1;
}
place_rect(x,y,w,h,c){
    _(I,x+w,x)
        _(J,y+h,y)P[J*U+I] = c;
}

fill_rest() {
    int x=0,y;
    while(++x<A) if (!P[x])break;
    if (x>=A) {
        _(i,V,0) printf("%*.*s\n", U,U, P+i*U);
        exit(0);
    }
    y = x / U; x -= y*U;

    _(i,N,0)
        if (!R.u & test_space(x, y, R.x, R.y))
                R.u = 1,
                place_rect(x, y, R.x, R.y, 'A'+i),
                fill_rest(),
                R.u = 0,
                place_rect(x, y, R.x, R.y, 0);

}

fill_y(i,y) {
    if (!R.u) {
        if (!test_space(0, y, R.x, R.y)) Z;
        R.u = 1;
        R.p = 0;
        place_rect(0, y, R.x, R.y, 'A'+i);
        y += R.y;
    }
    if (y == V) fill_rest();
    else _(j,N,0)
        if (j!=i && !r[j].u){ fill_y(j, y);
        while (r[j].x^r[j+1].x||r[j].y^r[j+1].y)j++;
        }
    R.u = 0;
    place_rect(R.p, (y -= R.y), R.x, R.y, 0);
}

fill_x(i,x) {
    if (!R.u) {
        if (R.x > U - x) Z;
        R.u = 1;
        R.p = x;
        place_rect(x, 0, R.x, R.y, 'A'+i);
        x += R.x;
    }
    if (x == U) fill_y(i, 1);
    else
        _(j,N,0)
            if (j!=i && !r[j].u) fill_x(j, x);
    place_rect((x -= R.x), 0, R.x, R.y, 0);
    R.u = 0;
}
C(int*a,int*b) {
    Z *a^*b?*a-*b:a[1]-b[1];
}


main() {
    _(i,25,0)
        if (++N&&scanf("%d %d\n", &R.x, &R.y)!=2) break;
    _(i,N,0){
        A+=R.x*R.y;
        if(R.x>X)X=R.x;
        if(R.y>Y)Y=R.y;
    }
    _(i,A+1,1)
        if (!(A%i)) {
            if (i < Y | A/i < X) continue;
            M++;
            S = realloc(S,M*16);
            S[M-1].y=i;
            S[M-1].x=A/i;
        }
    qsort(S, M, 16,C);
    P = calloc(A + 1,1);
    _(j,M,0){
        U = S[j].x; V = S[j].y;
        _(i,N,0)
            R.u = 1,
            place_rect(0, 0, R.x, R.y, 'A'+i),
            fill_x(i, R.x),
            R.u = 0;
    }
    printf("0\n");
    exit(1);
}

คำอธิบาย: เรามี 6 ฟังก์ชั่น: main, O, Q, F, และ L ไม่แน่ใจว่าจะมีพื้นที่สำหรับสี่เหลี่ยมที่จุดใดจุดหนึ่งหรือไม่ เพ็ญลิตร s สี่เหลี่ยมผืนผ้าลงในบัฟเฟอร์ส่งออกหรือสลับเอาหนึ่งโดยการเขียนทับมัน และสร้างกำแพงด้านซ้ายและด้านบนตามลำดับและเจ็บป่วยที่เหลือของสี่เหลี่ยมโดยการค้นหาซ้ำTT LOQF

แม้ว่าการค้นหาพื้นฐานนั้นซ้ำแล้วซ้ำอีกเราจะกำจัดเวกเตอร์การค้นหาที่เป็นไปได้ส่วนใหญ่ก่อนโดยการสร้างการรวมกันของความกว้างและความสูงที่อนุญาตสำหรับสี่เหลี่ยมหลักแล้วกำจัดการกำหนดค่าที่เป็นไปไม่ได้ ความเร็วเพิ่มเติมสามารถทำได้ในรูปสี่เหลี่ยมขนาดใหญ่โดยการกำหนดผนังด้านล่างและขวาก่อนที่จะเติมศูนย์ แต่ไม่จำเป็นสำหรับความเร็วที่เหมาะสมเมื่อ จำกัด ถึง 25 รูปสี่เหลี่ยมผืนผ้าภายใน


งานที่ดี! ดูเหมือนจะใช้งานได้ ... อย่างไรก็ตามคุณสามารถระบุรูปแบบผลลัพธ์ของคุณได้หรือไม่ ดูเหมือนว่ามันจะพิมพ์สิ่งต่าง ๆ ถ้ามันทำงานและล้มเหลวถ้ามันไม่ได้ซึ่งฉันจะอนุญาตเพราะนี่เป็นคำตอบเดียวเท่านั้น นอกจากนี้คุณสามารถบันทึกได้ไม่กี่ไบต์ด้วยการพิมพ์ "1" แทนที่จะเป็น "Everybody พอดี!" (เพราะได้รับอนุญาต) และยังค่อนข้างน้อยด้วยการไม่พิมพ์วิธีการจัดเรียง มันดีที่มีการพิมพ์ แต่ใช้ไบต์ที่ไม่จำเป็นและวัตถุประสงค์ก็เพื่อบันทึกสิ่งนั้น มิฉะนั้นงานดี! ฉันขยายกำหนดเวลาครึ่งเดือน แต่สำหรับตอนนี้มี upvote :)
HyperNeutrino

ขอบคุณ ฉันอัปเดตเพื่อระบุรูปแบบและแก้ไขข้อผิดพลาด (นั่นคือไม่ได้ตั้งใจ) ฉันทิ้งเอาท์พุทเมทริกซ์ (+ 30bytes) เพราะมันเป็นเรื่องที่ดีและถ้าคนอื่นโพสต์วิธีการแก้ปัญหากอล์ฟภาษาพวกเขาจะไม่เพียงแค่จะตีฉันโดย 30 :)
เซท

-367 bytes ... อาจเป็นสนามกอล์ฟที่ใหญ่ที่สุดหรือ :-)
HyperNeutrino

:-) มันช่วยให้มีจุดเริ่มต้นที่แฮ็ค -y
เซท

แน่นอน! กอล์ฟที่ใหญ่ที่สุดของฉันคือ 337 ตัวอักษรใน Java ในการแก้ไขหลายครั้งและฉันเริ่มต้นด้วยความคิดที่แย่มาก (โอ้วันเก่า ๆ ที่ดีเมื่อฉันจะสร้างตัวแปร 50 ล้านตัวและต้องการเพียง 2 ... ) อย่างไรก็ตามฉันจะรอคำตอบต่อไป แต่ดูเหมือนว่านี่อาจเป็นสิ่งเดียวที่ทำงานได้!
HyperNeutrino

6

Haskell, 226 ไบต์

((y,z):l)&(w,x)|x*y<1=(w+y,x+z):l
(q:l)&p=p:q:l
(p@(u,v):r@(y,z):l)%q@(w,x)=[((y-w,z):l)&q&(u,v-x)|w<=y,x<=v]++[p:m|m<-(r:l)%q]
_%_=[]
g m(p:n)l=any(g[]$m++n)(l%p)||g(p:m)n l
g[]_[_,_,_]=0<1
g _[]_=0<0
($[(0,9^9),(9^9,0)]).g[]

ลองใช้กับ Ideone

มันทำงานอย่างไร

การค้นหาแบบซ้ำ ๆ บางส่วนทั้งหมดที่มีรูปร่างเป็นไดอะแกรมแบบเรียกซ้ำโดยเพิ่มทีละหนึ่งสี่เหลี่ยมผืนผ้าและตรวจสอบว่าผลลัพธ์สุดท้ายใด ๆ เป็นสี่เหลี่ยมหรือไม่

หากต้องการดูว่าการเรียงตัวของสี่เหลี่ยมใด ๆ สามารถสร้างได้ด้วยวิธีนี้: ในการเรียงต่อกันของแผนภาพ Young ที่ไม่มีข้อ จำกัด ให้ R เป็นชุดของรูปสี่เหลี่ยมในการเรียงต่อกัน เนื่องจากจุดยอดเว้าแต่ละอันของแผนภาพหนุ่มนั้นอยู่ติดกับขอบ (ไม่ใช่แค่มุม - ติดกัน) จนถึงหนึ่งสี่เหลี่ยมใน R และจำนวนจุดยอดเว้าเหล่านี้จะน้อยกว่าจำนวนของรูปสี่เหลี่ยมใน R อย่างน้อยต้องมีอย่างน้อย สี่เหลี่ยมผืนผ้าหนึ่งใน R ที่อยู่ติดกับขอบซึ่งไม่มีจุดยอดเว้าเหล่านี้ การลบออกจะให้ไดอะแกรม Young อีกอันหนึ่งเพื่อให้เราสามารถดำเนินการต่อโดยการเหนี่ยวนำ


ทำได้ดีนี่! มันยอดเยี่ยมมาก เยี่ยมมาก! :)
HyperNeutrino
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.