เส้นทางที่สั้นที่สุดในกราฟตัวหาร


15

บทนำ

ในความท้าทายนี้เราจะจัดการกับบางกราฟไม่มีทิศทางที่ไม่มีที่สิ้นสุดซึ่งผมเรียกว่ากราฟหารสูง ต่อมน้ำมันเป็นจำนวนเต็มเริ่มตั้งแต่วันที่ 2 มีขอบอยู่ระหว่างสองโหนด<bถ้าแบ่งและ2 ≥ข กราฟย่อยที่เกิดขึ้นจากช่วง 2 ถึง 18 มีลักษณะดังนี้:

16-8 12 18
  \|/ |/|
   4  6 9 10 15 14
   |  |/   |/   |
   2  3    5    7  11 13 17

สามารถแสดงให้เห็นว่ากราฟตัวหารสูงที่ไม่มีที่สิ้นสุดเชื่อมต่อกันดังนั้นเราสามารถถามเกี่ยวกับเส้นทางที่สั้นที่สุดระหว่างสองโหนด

อินพุตและเอาต์พุต

ปัจจัยการผลิตของคุณเป็นจำนวนเต็มสองจำนวนและข คุณสามารถสรุปได้ว่า2 ≤≤ข <1000 เอาต์พุตของคุณคือความยาวของเส้นทางที่สั้นที่สุดระหว่างaและbในกราฟตัวหารสูงที่ไม่มีที่สิ้นสุด นี่หมายถึงจำนวนขอบในเส้นทาง

คุณอาจจะพบความจริงต่อไปนี้มีประโยชน์: มีอยู่เสมอเส้นทางที่ดีที่สุดจากเพื่อที่แรกที่เพิ่มขึ้นและลดลงแล้วและมีเพียงโหนดเข้าชมที่เป็นอย่างเคร่งครัดน้อยกว่า2b 2 โดยเฉพาะอย่างยิ่งตั้งแต่b <1,000คุณจะต้องพิจารณาโหนดที่น้อยกว่า 2 000 000

ตัวอย่าง

พิจารณาปัจจัยการผลิตและ3 32หนึ่งเส้นทางที่เป็นไปได้ระหว่างโหนด 3 และ 32 คือ

3 -- 6 -- 12 -- 96 -- 32

4เส้นทางนี้มีสี่ขอบและปรากฎว่าไม่มีเส้นทางที่สั้นลงเพื่อการส่งออกที่ถูกต้องคือ

เป็นอีกตัวอย่างหนึ่งเส้นทางที่ดีที่สุดสำหรับ2และ25คือ

2 -- 4 -- 8 -- 40 -- 200 -- 25

5เพื่อการส่งออกที่ถูกต้องคือ 50 = lcm(2, 25)ในกรณีนี้ไม่มีเส้นทางที่ดีที่สุดมีโหนด

กฎและการให้คะแนน

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

กรณีทดสอบ

2 2 -> 0
2 3 -> 4
2 4 -> 1
2 5 -> 5
3 5 -> 4
6 8 -> 2
8 16 -> 1
12 16 -> 2
16 16 -> 0
2 25 -> 5
3 32 -> 4
2 256 -> 3
60 77 -> 3
56 155 -> 3
339 540 -> 2
6 966 -> 4
7 966 -> 2
11 966 -> 4
2 997 -> 7
991 997 -> 4

ฉันมีความคิดที่ไม่ใช่แรงเดรัจฉานอย่างที่ฉันคิดมันนับจำนวนที่น้อยที่สุดของสองจำนวนทวีคูณทีละน้อยด้วยกำลังสองจนกระทั่งมันปรากฏขึ้นจากนั้นหารทีละน้อยด้วย sqrt จนกระทั่งตัวเลขที่สองปรากฏขึ้นฉันไม่มีเวลา เพื่อใช้ iy ตอนนี้แม้: /
Abr001am

Zgarb, Mathematica FindShortestPath ละเมิดข้อ จำกัด เกี่ยวกับช่องโหว่มาตรฐานหรือไม่? ถ้าเป็นเช่นนั้นเพียงแจ้งให้เราทราบและฉันจะลบการส่งของฉัน
DavidC

@ DavidC ฉันไม่คิดว่ามันเป็นช่องโหว่ คำตอบที่เกี่ยวข้องจริงมีคะแนน 0.
Zgarb

คำตอบ:


4

Matlab, 218 190 175 ไบต์

function f(a,b);q=a;l(b)=0;l(a)=1;while~l(b);x=q(1);q=q(2:end);l(end+1:x^2)=0;g=x+1:x^2;s=2:x-1;u=[g(~mod(g,x)),s(~mod(x,s)&s.^2>=x)];u=u(~l(u));q=[q,u];l(u)=l(x)+1;end;l(b)-1

ขอบคุณ @beaker สำหรับทางลัดในขั้นตอนการเพิ่มความยาวของรายการ!

นี่เป็นการใช้งาน dijkstra ที่ค่อนข้างตรงไปตรงมา:

q=a;                  %queue
l(b)=0;       %list of path lengths
l(a)=1;
while~l(b);         %if there is no predecessor to b
    x=q(1);         %get first queue element
    q=q(2:end);
    %add edges 
    l(end+1:x^2)=0;% lengthen predecessor list if too short
    g=x+1:x^2;      % g=greater neighbours
    s=2:x-1;        % s=smaller neighbours %keep only valid/unvisited neighbours 
    u=[g(~mod(g,x)),s(~mod(x,s)&s.^2>=x)]; %-1byte
    u=u(~l(u));
    q=[q,u];      %add only hte valid nodes edges to queue
    l(u)=l(x)+1;       %mark x as predecessor  
end;
l(b)-1 %output length to the end of the path

ไม่มีการโน้มน้าวใจวันนี้


2
แทนการl=zeros(1,a*b);ที่คุณสามารถใช้l(a*b)=0;ซึ่งไม่เหมือนกัน
หลุยส์ Mendo

อนิจจา .... ยังมีความยาว 10 ไบต์อยู่ข้างหลังคุณ
Abr001am

1

JavaScript (ES6), 186 ไบต์

(m,n)=>(g=i=>{for(q=[i],r=[],r[i]=j=0;i=q[j++];)for(k=i+i;k<=i*i&(k<m*m*2|k<n*n*2);k+=i)r[k]-r[i]<2?0:r[q.push(k),k]=r[i]+1},g(m),s=r,g(n),Math.min(...r.map((i,j)=>i+s[j]).filter(i=>i)))

ใช้ฟังก์ชั่นผู้ช่วยgในการคำนวณทุกเส้นทางจากน้อยไปมากจากmและnในที่สุดก็ถึงขีด จำกัด ให้แล้วสรุปเส้นทางร่วมกันและผลตอบแทนที่คุ้มค่าต่ำสุด


1

Mathematica 98 ไบต์

ฉันสมมติว่าฟังก์ชั่นในตัว FindShortestPathไม่ละเมิดข้อ จำกัด เกี่ยวกับช่องโหว่มาตรฐาน ถ้าเป็นเช่นนั้นเพียงแจ้งให้เราทราบและฉันจะลบการส่งนี้

bแรงโง่จึงชะลอตัวที่มีค่ามาก ฉันยังคงคิดหาวิธีที่จะเร่งความเร็ว

h@{a_,b_}:=Length@FindShortestPath[Graph[Apply[Join,Thread[#<->Range[2,#] #]&/@Range[b^2]]],a,b]-1

ชุดนี้ขึ้นกราฟที่มีขอบที่เหมาะสมระหว่างโหนดจากไปa ค้นหาเส้นทางที่สั้นที่สุดในกราฟ นับโหนด คือจำนวนขอบ b^2FindShortestPathLengthLength -1

Thread[# <-> Range[2, #] #] &สร้างขอบของกราฟแบบเต็ม ยกตัวอย่างเช่น Thread[# <-> Range[2, #] #]&[5]จะผลิตขอบ{5 <-> 2*5, 5 <-> 3*5, 5 <-> 4*5, 5 <-> 5*5}, {5 <-> 10, 5 <-> 15, 5 <-> 20, 5 <-> 25}ที่อยู่,


1

Matlab (195) (185) (181) (179)(173)

หมายเหตุ:ฉันเป็นผู้ใช้ Agawa001 เป็นการส่วนตัวฉันยืนยันว่าฉันชนะมากกว่าผู้ใช้ @flawr โดยใช้ความช่วยเหลือของเขา

 function t(a,b,p),for r=0:1,d=(b*~r+r*a)/gcd(a,b);while(d>1)p=p+1;e=find(~rem(d,1:d));f=max(e(a^(1-r/2)>=e));a=a*min([find(1:a*a>=b) a])^~(f-1);d=d/f;a=a*f^(1-2*r);end,end,p
  • ฟังก์ชั่นนี้แตกต่างจากที่อื่นมันทำตามการคำนวณทางคณิตศาสตร์และการแยกตัวประกอบทางคณิตศาสตร์ล้วน แต่ไม่มีอะไรเกี่ยวข้องกับเส้นทางหรือกราฟ
  • ตัวอย่างการเรียกใช้ฟังก์ชัน:

     t(2,3,0)
    
     p =
    
     4
    

    ทุกกรณีทดสอบมีความพึงพอใจ

  • คำอธิบาย:

ก่อนที่จะเริ่มต้นด้วยคำอธิบายให้พิสูจน์บางบทแทรก "ไม่ใช่คำเขียว"

บทแทรก (1):เส้นทางที่ดีที่สุดระหว่างตัวเลขสองตัวใด ๆ ที่(a,b)มีอยู่ในวิธีที่โหนดจะเพิ่มขึ้นในตอนแรกแล้วลดลง

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

เล็มม่า (2):จากจำนวนaถึงbถ้าgcd(a,b)=1 aคูณด้วยbถ้าbใหญ่กว่าaมันจะถูกคูณด้วยจำนวนที่รู้จักcถ้าgcd>1 aต้องคูณด้วยตัวหารที่ใหญ่ที่สุดของb/gcdชื่อdที่จะตรวจสอบสภาพa >= dเมื่อทุกคนdคือ ขั้นต่ำที่มีขนาดใหญ่กว่าa, aได้รับa*cอีกครั้ง

สมมติฐานนี้เป็นเรื่องง่ายที่จะพิสูจน์ว่าโหนดเริ่มต้นใด ๆaจะต้องคูณจนกระทั่งถึงจำนวนที่น้อยที่สุดaและbเราจะคูณด้วยสัดส่วนของการb*gcdเริ่มต้นด้วยจำนวนสูงสุดซึ่งตรวจสอบเงื่อนไขหลักที่รับประกันเส้นทางที่สั้นที่สุดไปยัง smp ก่อนกระบวนการเริ่มต้น หรือเมื่อdไม่มีหมายเลขcจะถูกคูณด้วยaเพื่อให้เงื่อนไขที่ถูกต้องa>=dสำหรับระยะแรกนี้

เลมม่า (3):จากกราฟที่มีหลายค่าสูงสุดaถึงbgcd ของจำนวนนี้และbเป็นของbตัวเอง

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

Dilemma:อะไรคือจำนวนที่เหมาะสมที่สุดที่cจะถูกคูณซ้ำโดยaที่จะนำไปสู่สภาพการเปิดสำหรับระยะที่ 1 แล้วขั้นสูงสุด

เป็นคำถามที่ดีสำหรับสถานการณ์ที่เรียบง่ายมีการปัดป้องแบบง่ายดังนั้นสมมติว่าตัวอย่างของการจบทั้งสอง(a,b)=(4,26)แยกเป็นดังนี้:

  2 | 2
  2 | 13

นอกเหนือจากgcd=2จำนวนเต็มเล็กชจะต้องคูณด้วย2การเข้าถึง13เป็น7แต่มันถูกปกครองอย่างเห็นได้ชัดออก cuz มันมีขนาดใหญ่กว่า 2 เพื่อเป็นกำลังสอง

  2 | 2 
  5 | 13

Appearenlty ในตัวอย่างที่สอง(a,b)=(10,26)ดังกล่าวข้างต้นcเป็นวัดที่เป็นจำนวนเต็มต่ำสุดจาก1การ5ที่เกิน13/5จึงตอบสนองเงื่อนไขของกราฟปรับซึ่งเป็น3ดังนั้นขั้นตอนต่อไปที่นี่จะคูณด้วย3

  2 | 2 
  5 | 13
  3 |

ทำไม นี่เป็นเพราะเมื่อเราต้องคูณด้วย2*13/gcd=13เพื่อให้ตรงกับด้านที่สองของตารางปริมาณขยะที่เราเพิ่มเข้าไปก่อนจะเล็กที่สุดอย่างเหมาะสมและการเคลื่อนที่ไปตามกราฟจะถูกย่อให้เล็กสุดถ้าเราคูณด้วยค่าที่มากขึ้นเช่น10โอกาสหารด้วย เวลาอย่างน้อยจะช่วยลดและมันจะได้รับเพิ่มขึ้นจาก 1 2*13อีกหนึ่งขั้นตอนการหารที่จะบรรลุเป้าหมายของเรา ซึ่งมีการแจกแจงที่: แล้ว13*2*5*10/2*5 13*2*5/5ในขณะที่เห็นได้ชัดว่าจำนวนที่จะหารด้วยคือ5*3<13*2

และอีกอย่างหนึ่ง ........ HAIL MATHS ...


เหล่านี้เป็นผลลัพธ์เชิงเปรียบเทียบของฉันกับ @flawr 'sเพียงแค่ให้ความสนใจว่าฉันได้ทำขอบเขตบนสำหรับเวลาดำเนินการที่เกี่ยวข้องกับอัลกอริทึมของข้อบกพร่องมันใช้เวลามากเกินไป!

คุณสามารถแทรกช่วงเริ่มต้นและจุดสิ้นสุดการสแกนเป็นตัวแปร a และ b ในส่วนหัวของรหัสที่คอมไพล์ออนไลน์ได้


ว้าวนี่เป็นเรื่องน่าประหลาดใจ ฉันไม่ได้คาดหวังว่าเส้นทางที่ดีที่สุดสามารถสร้างขึ้นได้อย่างตรงไปตรงมา รอคอยที่จะอธิบาย ...
Zgarb

@Zgarb ฉันได้อธิบายเล็กน้อยในความคิดเห็นโพสต์หลักฉันจะโมบรรเลงเมื่อฉันเล่นกอล์ฟเสร็จแล้ว btw ช่างเป็นความท้าทายที่ดีที่ไม่เหมือนใคร!
Abr001am

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