การปูกระเบื้องเรียบง่ายที่สุดของพื้น


10

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

พื้นเป็นส่วนหนึ่งของตารางสี่เหลี่ยม กระเบื้องสี่เหลี่ยมทุกแผ่นมีสีฟ้าหรือดำ (แสดงโดยaและbในอินพุต)

ตัวอย่างชั้น:

  aaaa
ababab
aaaaa

meta-tiling

  • ที่ถูกสร้างขึ้นจากNจากMสี่เหลี่ยม meta-กระเบื้องสี่เหลี่ยมสีฟ้าและสีดำ
  • meta-tiles ที่ใช้เหมือนกันกับการแปล (คุณไม่สามารถหมุนหรือมิเรอร์)
  • หากด้านข้างของแผ่นเมตาทั้งสองมีการเชื่อมต่อพวกเขาควรเชื่อมต่อตามความยาวทั้งหมดของพวกเขา (เช่นแผ่นกระเบื้องเมตาพื้นที่ในลักษณะคล้ายกริด)

ตัวอย่าง meta-tile:

ba
aa

และการปูกระเบื้องเมตาสร้างโดย:

       .
       .
       .
    babababa
    aaaaaaaa
... babababa ...
    aaaaaaaa    
    babababa
    aaaaaaaa
       .
       .
       .

การเรียงข้อมูลเมตานี้จะสร้างชั้นที่แสดงอยู่ด้านบนเมื่อตัวอักษรซ้ายแสดง:

       .
       .
       .
    ********
    ***aaaa*
... *ababab* ...
    *aaaaa**    
    ********
    ********
       .
       .
       .

การเรียง meta-tiling นั้นง่ายกว่าแบบอื่นหากพื้นที่ของ meta-tile มีขนาดเล็กลง ตัวอย่างของเรามีพื้นที่2*2 = 4ที่เล็กที่สุดเท่าที่จะเป็นไปได้สำหรับตัวอย่างชั้น ดังนั้นผลลัพธ์ควรเป็น4ตัวอย่าง

อินพุต

  • สตริงที่ประกอบด้วยตัวอักษรa b spaceและnewlineมีอย่างน้อยหนึ่งหรือab
  • ตัวอักษร ( ab) สร้างรูปร่างที่เชื่อมต่อ 4 แบบ (ต่อกัน)
  • จะไม่มีช่องว่างที่ไม่จำเป็นที่ด้านหน้าของแถวคือจะมีอย่างน้อยหนึ่งแถวเริ่มต้นด้วยหรือab
  • คุณสามารถเลือกรูปแบบการป้อนข้อมูลได้สองแบบ:

    • ไม่มีช่องว่างที่ไม่จำเป็นที่ท้ายแถว (ดังที่เห็นในตัวอย่าง)
    • ช่องว่างทางด้านขวาของแถวเพื่อทำให้แถวทั้งหมดยาวเท่ากันกับแถวที่ยาวที่สุด
  • ขึ้นบรรทัดใหม่ต่อท้ายเป็นตัวเลือก

เอาท์พุต

  • จำนวนเต็มเดียวพื้นที่ของ meta-tile ที่เล็กที่สุดเท่าที่เป็นไปได้ซึ่งมีการเรียงต่อกันมีการปูพื้นการป้อนข้อมูล

ตัวอย่าง

ตัวอย่างคั่นด้วยขีดกลาง ตัวอย่างสามส่วนคืออินพุตเอาต์พุตและหนึ่งในกระเบื้องเมตาดาต้าที่เล็กที่สุดที่เป็นไปได้

a

1

a
-----------------
 aaaa
aaa
a

1

a
-----------------
aabaab
abaa
aaba

6

aab
aba
-----------------
aabaab
a  a a
aabab

18

aabaab
aaaaaa
aababa
-----------------
ba
aaab

8

baaa
aaab
-----------------
 aaaa
ababb
aaaa

10

aaaaa
ababb
-----------------
 a aa
ab ba
 aba

6

aa
ab
ba
-----------------
 aaaa
abab
aaaa

4

aa
ab
-----------------
ba
 ba
  b

4

ba
ab
-----------------
baa
aba
aab

9

baa
aba
aab
-----------------
 aaaa
aabaa
aaaa

6

aaa
aab

นี่คือรหัสกอล์ฟเพื่อให้รายการที่สั้นที่สุดชนะ


@Ypnypn ทุกมุมจะต้องแตะอีก 3 มุม (ยกเว้นเมตาไทล์ที่ขอบของการเรียงต่อกัน) ฉันระบุว่า "ถ้าด้านข้างของกระเบื้องเมตาทั้งสองเชื่อมต่อกันพวกเขาควรเชื่อมต่อไปตามความยาวทั้งหมด" ตัวอย่างที่คุณให้นั้นผิดกฎหมาย
randomra

คำตอบ:


3

C - 208 ไบต์

w,q,n,m,r,g,u;t(char*f){for(w=0;f[w++]-10;);for(q=1;;q++)for(n=1;m=q/n,n<=q;++n)if(n*m==q){char t[q];bzero(t,q);r=q;for(g=0;f[g];++g){u=g/w%m*n+g%w%n;r=t[u]+f[g]-195?r:0;if(f[g]&64)t[u]=f[g];}if(r)return r;}}

รหัสเทียบเท่าก่อนเล่นกอล์ฟ:

#include <stdio.h>
#include <strings.h>

int t(char* f) {
    int w = 0;
    for ( ; f[w++] - 10; );

    for (int q = 1; ; q++) {
        char t[q];
        for (int n = 1; n <= q; ++n) {
            int m = q / n;
            if (n * m == q) {
                bzero(t, q);
                int r = q;
                for (int g = 0; f[g]; ++g) {
                    int u = g / w % m * n + g % w % n;
                    if (t[u] + f[g] == 195) {
                        r = 0;
                    }
                    if (f[g] & 64) {
                        t[u] = f[g];
                    }
                }
                if (r) {
                    return r;
                }
            }
        }
    }
}

อัลกอริธึมนั้นค่อนข้างดุร้ายดังนั้นจึงควรมีเหตุผลชัดเจนว่ามันทำงานอย่างไรบนพื้นฐานของโค้ด นี่คือความคิดเห็นบางส่วนอยู่แล้ว:

  • อินพุตคาดว่าจะมีรูปแบบที่มีช่องว่างต่อท้ายเพื่อให้ทุกบรรทัดมีความยาวเท่ากัน
  • วงแรกค้นหาความกว้างโดยค้นหาอักขระขึ้นบรรทัดใหม่ตัวแรก
  • qห่วงด้านนอกเป็นผู้สมัครมากกว่าขนาด meta-กระเบื้อง ออกด้วยreturnเมื่อเมตาไทล์กระเบื้องสามารถครอบคลุมพื้น โปรดทราบว่าการวนซ้ำไม่ต้องการเงื่อนไขการออกอื่นเนื่องจากมีวิธีแก้ไขอยู่เสมอ (กรณีที่แย่ที่สุดคือขนาดของอินพุต)
  • วงซ้อนกันครั้งแรกและต่อไปนี้ifระบุ meta-กระเบื้องรวมกันกว้าง / qสูงที่ถูกต้องสำหรับขนาด
  • อาร์เรย์อักขระที่ตรงกับขนาด meta-tile ของผู้สมัครจะถูกกำหนดค่าเริ่มต้นเป็นศูนย์
  • วนรอบด้านในวนซ้ำไปมาบนกระเบื้องทั้งหมดในพื้น
  • u คือดัชนีใน meta-tile ที่สอดคล้องกับกระเบื้องปูพื้น
  • หากทั้งกระเบื้องปูพื้นและแผ่นกระเบื้องเมตาคือaหรือbแตกต่างกัน (ผลรวมของa = 97และb = 98เป็น195 ) มีความไม่ตรงกันและขนาดของกระเบื้องเมตากับขนาดที่พยายามจะไม่ทำงาน
  • มิฉะนั้นถ้ากระเบื้องปูพื้นเป็นaหรือbสีกระเบื้องจะถูกคัดลอกไปยัง meta-tile ตัวเลือก
  • ส่งคืนขนาดของเมตาไทล์เมื่อทำการจับคู่ที่ประสบความสำเร็จเช่นหากการจับคู่ที่พยายามทำไม่มีการทำเครื่องหมายว่าล้มเหลว

รหัสทดสอบที่ใช้:

#include <stdio.h>

extern int t(char* s);

int main()
{
    printf("%d\n", t(
        "a\n"
    ));
    printf("%d\n", t(
        " aaaa\n"
        "aaa  \n"
        "a    \n"
    ));
    printf("%d\n", t(
        "aabaab\n"
        "abaa  \n"
        "aaba  \n"
    ));
    printf("%d\n", t(
        "aabaab\n"
        "a  a a\n"
        "aabab \n"
    ));
    printf("%d\n", t(
        "ba  \n"
        "aaab\n"
    ));
    printf("%d\n", t(
        " aaaa\n"
        "ababb\n"
        "aaaa \n"
    ));
    printf("%d\n", t(
        " a aa\n"
        "ab ba\n"
        " aba \n"
    ));
    printf("%d\n", t(
        " aaaa\n"
        "abab \n"
        "aaaa \n"
    ));
    printf("%d\n", t(
        "ba \n"
        " ba\n"
        "  b\n"
    ));
    printf("%d\n", t(
        "baa\n"
        "aba\n"
        "aab\n"
    ));
    printf("%d\n", t(
        " aaaa\n"
        "aabaa\n"
        "aaaa \n"
    ));
    return 0;
}

เอาท์พุท:

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