দাবাতিলে নাইটের সবচেয়ে সংক্ষিপ্ত পথ


96

আমি একটি আসন্ন প্রোগ্রামিং প্রতিযোগিতার জন্য অনুশীলন করে চলেছি এবং আমি এমন একটি প্রশ্নের মুখোমুখি হোঁচট খেয়েছি যে আমি পুরোপুরি বিস্মিত হয়েছি। যাইহোক, আমি মনে করি যেন এটি আমার ধারণাটি আমার আঙ্গুলগুলি অতিক্রম করার চেয়ে এখন শেখা উচিত যা কখনই সামনে আসে না।

মূলত, এটি দাবা বোর্ডে একটি নাইট টুকরা নিয়ে কাজ করে। আপনাকে দুটি ইনপুট দেওয়া হবে: শুরু করা অবস্থান এবং শেষের অবস্থান। লক্ষ্যটি হ'ল নাইটটি লক্ষ্য স্থানে পৌঁছতে পারে এমন সবচেয়ে সংক্ষিপ্ত পথটি গণনা এবং মুদ্রণ করা।

আমি কখনও সংক্ষিপ্ততম-পাথের-সংক্রান্ত জিনিসগুলির সাথে কাজ করি নি এবং কোথা থেকে শুরু করব তাও জানি না। এটি মোকাবেলা করার জন্য আমি কোন যুক্তি ব্যবহার করব?

পিএস যদি এটি কোনও প্রাসঙ্গিকতার হয় তবে তারা চান যে আপনি নাইটের সাধারণ চালগুলি পরিপূরক করে এটিও বদ্ধ চৌকোটি কোণে (সম্ভাব্য) আটটি নাইট তৈরি করতে পারবেন যা প্রদত্ত বর্গটির কেন্দ্রস্থলকে প্রদত্ত করে দেওয়া উচিত নাইটের অবস্থান


আপনি কি PS স্পষ্ট করতে পারেন? আপনার অর্থ, কোনও নাইট যদি E4 এ থাকে তবে এটি সি 2, সি 6, জি 2 এবং জি 6 এ যেতে পারে?
স্টিভ তেজোয়া

হ্যাঁ, এটি স্বাভাবিক চাল ছাড়াও।
কাইল হিউজেস

4
সমস্যাটির কিছু গাণিতিক বিশ্লেষণ এখানে দেওয়া হয়েছে: math.stackexchange.com/questions/104700/…
গ্রিম পাইল

উত্তর:


28

আপনার এখানে একটি গ্রাফ রয়েছে, যেখানে সমস্ত উপলভ্য পদক্ষেপ সংযুক্ত রয়েছে (মান = 1), এবং অনুপলভ্য পদক্ষেপগুলি সংযোগ বিচ্ছিন্ন হয়েছে (মান = 0), স্পার্স ম্যাট্রিক্স এর মতো হবে:

(a1,b3)=1,
(a1,c2)=1,
  .....

এবং গ্রাফের দুটি পয়েন্টের সংক্ষিপ্ততম পথটি http://en.wikedia.org/wiki/Dijkstra's_algorithm ব্যবহার করে পাওয়া যাবে

উইকিপিডিয়া পৃষ্ঠা থেকে সিউডো কোড:

function Dijkstra(Graph, source):
   for each vertex v in Graph:           // Initializations
       dist[v] := infinity               // Unknown distance function from source to v
       previous[v] := undefined          // Previous node in optimal path from source
   dist[source] := 0                     // Distance from source to source
   Q := the set of all nodes in Graph
   // All nodes in the graph are unoptimized - thus are in Q
   while Q is not empty:                 // The main loop
       u := vertex in Q with smallest dist[]
       if dist[u] = infinity:
          break                         // all remaining vertices are inaccessible from source
       remove u from Q
       for each neighbor v of u:         // where v has not yet been removed from Q.
           alt := dist[u] + dist_between(u, v) 
           if alt < dist[v]:             // Relax (u,v,a)
               dist[v] := alt
               previous[v] := u
   return dist[]

সম্পাদনা:

  1. মুরন হিসাবে, http://en.wikedia.org/wiki/A*_algorithm ব্যবহার করে বলেছিলেন দ্রুততর হতে পারে।
  2. দ্রুততম উপায় হ'ল সমস্ত দূরত্বের প্রাক-গণনা এবং এটি 8x8 পূর্ণ ম্যাট্রিক্সে সংরক্ষণ করা। ঠিক আছে, আমি সেই প্রতারণাকে কল করব এবং সমস্যাটি কম হওয়ায় কেবল কাজ করে। তবে কখনও কখনও প্রতিযোগিতাগুলি আপনার প্রোগ্রামটি কত দ্রুত চলে তা পরীক্ষা করে দেখবে।
  3. মূল কথাটি হ'ল আপনি যদি কোনও প্রোগ্রামিং প্রতিযোগিতার জন্য প্রস্তুতি নিচ্ছেন তবে আপনাকে অবশ্যই ডিজকস্ট্রার সহ সাধারণ অ্যালগরিদমগুলি জানতে হবে। একটি ভাল সূচনা পয়েন্ট Introduction to AlgorithmsISBN 0-262-03384-4 পড়ছে । অথবা আপনি উইকিপিডিয়া চেষ্টা করতে পারেন, http://en.wikedia.org/wiki/List_of_algorithms

এটি নীচে মোস্তফার সমাধানের তুলনায় জটিল বলে মনে হচ্ছে।
lpapp

অনুপলব্ধ পদক্ষেপের অর্থ কী? একটি নাইট ঠিক যে কোনও স্কোয়ারে পৌঁছতে পারে !?
চিরস্থায়ী

51

সম্পাদনা: সাইমনের উত্তর দেখুন , যেখানে তিনি এখানে উপস্থাপিত সূত্রটি স্থির করেছিলেন।

আসলে একটি ও (1) সূত্র আছে

এটি এমন একটি চিত্র যা আমি এটি ভিজ্যুয়ালাইজ করার জন্য তৈরি করেছি (স্কয়ারগুলি একটি নাইট এন মাইভে পৌঁছাতে পারে একই রঙে আঁকা হয়)। নাইটস মুভ

আপনি কি এখানে প্যাটার্নটি লক্ষ্য করতে পারেন?

যদিও আমরা প্যাটার্নটি দেখতে পাচ্ছি, f( x , y )বর্গ থেকে যেতে প্রয়োজনীয় পদক্ষেপের সংখ্যাটি ফিরিয়ে দেয় এমন ফাংশনটি খুঁজে পাওয়া সত্যিই শক্ত( 0 , 0 ) স্কোয়ারে( x , y )

কিন্তু এখানে সূত্র যে কাজ করে 0 <= y <= x

int f( int x , int y )
{
    int delta = x - y;

    if( y > delta )
        return 2 * ( ( y - delta ) / 3 ) + delta;
    else
        return delta - 2 * ( ( delta - y ) / 4 );
}

দ্রষ্টব্য: এই প্রশ্নটি SACO 2007 দিবস 1 এ জিজ্ঞাসা করা হয়েছিল
এবং সমাধানগুলি এখানে রয়েছে


8
আপনি কীভাবে সেই সূত্রটি কার্যকর করেছিলেন তা আপনি বর্ণনা করতে পারেন?
কায়বার্নটিকোস

4
এই কোড কাজ করে? যদি কোনও নাইট পজিশন হয় (0,0) এবং আমি এটি পয়েন্টে স্থানান্তর করতে চাই (1,0)। এটি 0 <= y <= x সন্তুষ্ট করে। ব-দ্বীপ = 1-0 = 1. y ডেল্টার চেয়ে বড় নয় (0 <1) is এর অর্থ আমি অন্য মামলায় যাচ্ছি। ব-দ্বীপ - 2 * ((ব-দ্বীপ - y) / 4) = 1-2 ((1-0) / 4) = 1-1 / 2 = 1। আমি কোনও পদক্ষেপে নাইটকে (0,0) থেকে (1,0) এ স্থানান্তর করতে পারি না! প্রশ্ন এই অ্যালগোরিটম কাজ করে? বা আমি কি ভুল করছি?
সিম্পল অ্যাপ্লিকেশন 7'15

4
দেখে মনে হচ্ছে এটি কেবল সরাসরি সম্ভাব্য পজিশনের জন্য কাজ করে। তবে ব্যবহারকারী যদি (2,2) সরবরাহ করে তবে এটি 0 প্রদান করে এবং যদি ব্যবহারকারী (4,4) সরবরাহ করে তবে এটি 2 ফেরত দেয় যা ভুল।
ইউনাস

6
এটা হওয়া উচিত 2 * floor((y - delta) / 3) + deltaএবং delta - 2 * floor((delta - y) / 4)। এটি এই প্রতিযোগিতার পৃষ্ঠা থেকে সরকারী সমাধান, তবে এটি ভুল। এই প্রথম সমীকরণ (থেকে if) ভুল উত্তর দেয়। দাবাবোর্ডে [-1000..1000] x [-1000..1000], যা 2001x2001 বড় (তবে যুক্তিযুক্তভাবে সীমাহীন), প্রদত্ত উত্তরটি 4,004,001 ক্ষেত্রের (6,66%) সঠিক হিসাবে 2,669,329 গণনা করেছে। কেউ কোনও লুপ ছাড়াই কাজের সমাধান জানেন?
রোবো রোবক

4
আমি এই সমাধান কাজ করে না সম্মত। ওয়ার্কিং ও (1) সমাধানের জন্য অন্যান্য উত্তর যেমন stackoverflow.com/a/26888893/4288232 দেখুন ।
টিএমএসসি

45

এখানে একটি সঠিক ও (1) সমাধান রয়েছে, তবে যে ক্ষেত্রে কেবল একটি দাবা নাইটের মতো নাইট চলে এবং সেই অসীম দাবা বোর্ডে:

https://jsfiddle.net/graemian/5qgvr1ba/11/

এটি সন্ধানের মূল বিষয়টি হ'ল বোর্ডটি আঁকলে উত্থিত নিদর্শনগুলি লক্ষ্য করা। নীচের চিত্রে, স্কোয়ারের সংখ্যাটি হল সেই বর্গাকারে পৌঁছানোর জন্য প্রয়োজনীয় ন্যূনতম সংখ্যা (আপনি এটি সন্ধানের জন্য প্রস্থের প্রথম অনুসন্ধান ব্যবহার করতে পারেন):

প্যাটার্নস

সমাধানটি অক্ষ এবং ত্রিভুজ জুড়ে সমান্তরাল হওয়ায় আমি কেবল x> = 0 এবং y> = x কেসটি আঁকলাম।

নীচে-বাম ব্লকটি শুরুর অবস্থান এবং ব্লকগুলির সংখ্যাগুলি এই ব্লকগুলিতে পৌঁছানোর ন্যূনতম সংখ্যাটির প্রতিনিধিত্ব করে।

3 টি নিদর্শন লক্ষ্য করা যায়:

  • 4 এর নীল উল্লম্ব গ্রুপগুলি বৃদ্ধি করছে
  • "প্রাথমিক" লাল ত্রিভুজ (তারা ব্যাকস্ল্যাশের মতো উপরে-বাম থেকে নীচে-ডানদিকে চালায়)
  • "গৌণ" সবুজ বর্ণগুলি (লাল রঙের মতো একই দিক)

(নিশ্চিত হোন যে আপনি উভয় সেটটি ডান দিকের উপরে-বাম থেকে নীচে-ডান হিসাবে দেখতে পেয়েছেন They তাদের একটি ধ্রুবক পদক্ষেপ-গণনা রয়েছে bottom

আপনি প্রতিটি জন্য সূত্র প্রাপ্ত করতে পারেন। হলুদ ব্লকগুলি বিশেষ ক্ষেত্রে। সুতরাং সমাধানটি হয়ে যায়:

function getMoveCountO1(x, y) {

    var newXY = simplifyBySymmetry(x, y);

    x = newXY.x;
    y = newXY.y;

    var specialMoveCount = getSpecialCaseMoveCount(x ,y);

    if (specialMoveCount !== undefined)
        return specialMoveCount;

    else if (isVerticalCase(x, y))
        return getVerticalCaseMoveCount(x ,y);

    else if (isPrimaryDiagonalCase(x, y))
        return getPrimaryDiagonalCaseMoveCount(x ,y);

    else if (isSecondaryDiagonalCase(x, y))
        return getSecondaryDiagonalCaseMoveCount(x ,y);

}

সবচেয়ে শক্তভাবে উল্লম্ব দলগুলির সাথে:

function isVerticalCase(x, y) {

    return y >= 2 * x;

}

function getVerticalCaseMoveCount(x, y) {

    var normalizedHeight = getNormalizedHeightForVerticalGroupCase(x, y);

    var groupIndex = Math.floor( normalizedHeight / 4);

    var groupStartMoveCount = groupIndex * 2 + x;

    return groupStartMoveCount + getIndexInVerticalGroup(x, y);

}

function getIndexInVerticalGroup(x, y) {

    return getNormalizedHeightForVerticalGroupCase(x, y) % 4;

}

function getYOffsetForVerticalGroupCase(x) {

    return x * 2;

}

function getNormalizedHeightForVerticalGroupCase(x, y) {

    return y - getYOffsetForVerticalGroupCase(x);

}

অন্যান্য মামলার জন্য বেড়া দেখুন।

আমি মিস করেছি আরও সহজ বা আরও মার্জিত নিদর্শন আছে? যদি তা হয় তবে আমি সেগুলি দেখতে পছন্দ করব। বিশেষত, আমি নীল উল্লম্ব ক্ষেত্রে কিছু তির্যক নিদর্শন লক্ষ্য করি, কিন্তু আমি সেগুলি অন্বেষণ করি নি। নির্বিশেষে, এই সমাধান এখনও ও (1) সীমাবদ্ধাকে সন্তুষ্ট করে।


এটি (আক্ষরিক) কোণার কেসগুলি পরিচালনা করবে বলে মনে হয় না। যদি "0" বোর্ডের নীচে বাম বর্গক্ষেত্র হয় (a1), তবে আপনি দুটি চালক্রমে নিকটতম "2" স্পেস (বি 2) এ যেতে পারবেন না। কারণ এটি করার জন্য আপনার প্রথম পদক্ষেপটি (এ 3) এর বামে অস্তিত্বহীন স্থানের হতে হবে।
জন হাস্কল

ঠিক আছে, আমি অসীম দাবা বোর্ড অনুমান অন্তর্ভুক্ত করার জন্য আমার উত্তরটি পরিবর্তন করেছি
গ্রীম পাইল

@ জোনাটাসওয়াকার দয়া করে ব্যাখ্যা করুন, আমি (8,0) থেকে (0,0) যেতে কোনও সমস্যা দেখছি না। এটি 4 চলন লাগে?
গ্রিম পাইল

দুঃখিত @ গ্রেইমপাইল, আমার দোষ, আমার মন্তব্য মুছে ফেলছে।
জোনাটাস ওয়াকার

4
হাই @ গ্র্যাম্পাইল - আমি আপনার সাথে একমত হই এটি সেরা সামগ্রিক প্রোগ্রামিং পদ্ধতির is দারুণ ডায়াগ্রাম!
ফ্যাটি

22

খুব আকর্ষণীয় সমস্যা যা আমি সম্প্রতি সম্মুখীন হয়েছিলাম। কিছু সমাধান দেখার পরে আমাকে SACO 2007 দিন 1 সমাধানগুলিতেO(1) time and space complexity প্রদত্ত বিশ্লেষণাত্মক সূত্রটি পুনরুদ্ধার করার চেষ্টা করা হয়েছিল ।

সবার আগে আমি খুব সুন্দর ভিজ্যুয়ালাইজেশনের জন্য গ্র্যাম পাইকে প্রশংসা করতে চাই যা সূত্র ঠিক করতে আমাকে সহায়তা করেছিল।

কোনও কারণে (সম্ভবত সরলীকরণ বা সৌন্দর্য বা কেবল একটি ভুলের জন্য) তারা অপারেটরে minusসাইন সরিয়ে floorনিয়েছিল, ফলস্বরূপ তারা ভুল সূত্র পেয়েছেfloor(-a) != -floor(a) for any a

সঠিক বিশ্লেষণ সূত্রটি এখানে:

var delta = x-y;
if (y > delta) {
    return delta - 2*Math.floor((delta-y)/3);
} else {
    return delta - 2*Math.floor((delta-y)/4);
}

সূত্রটি (1,0) এবং (2,2) কোণার কেসগুলি বাদ দিয়ে সমস্ত (x, y) জোড়া (অক্ষ এবং তির্যক প্রতিসাম্য প্রয়োগের পরে) জন্য কাজ করে, যা নিদর্শনকে সন্তুষ্ট না করে এবং নিম্নলিখিত স্নিপেটে হার্ডকোডযুক্ত:

function distance(x,y){
     // axes symmetry 
     x = Math.abs(x);
     y = Math.abs(y);
     // diagonal symmetry 
     if (x < y) {
        t = x;x = y; y = t;
     }
     // 2 corner cases
     if(x==1 && y == 0){
        return 3;
     }
     if(x==2 && y == 2){
        return 4;
     }
    
    // main formula
    var delta = x-y;
		if(y>delta){
  		return delta - 2*Math.floor((delta-y)/3);
  	}
  	else{
  		return delta - 2*Math.floor((delta-y)/4);
  	}
}


$body = $("body");
var html = "";
for (var y = 20; y >= 0; y--){
	html += '<tr>';
	for (var x = 0; x <= 20; x++){
  	html += '<td style="width:20px; border: 1px solid #cecece" id="'+x+'_'+y+'">'+distance(x,y)+'</td>';
  }
  html += '</tr>';
}

html = '<table>'+html+'</table>';
$body.append(html);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

দ্রষ্টব্য: কোড দেখুন distanceফাংশনের জন্য jQuery কেবল চিত্রের জন্য ব্যবহৃত হয়।


4
@ ওলেগআব্রাজাইভ "দূরত্ব" ফাংশন একটি বিশ্লেষণমূলক ফাংশন এবং ও (1) সময়ে প্রদত্ত (x, y) পজিশনের জন্য বহু পদক্ষেপের গণনা করতে পারে। মূলত এই সূত্রে আমরা বোর্ডের উপর নির্ভর করি না (আমার ধারণা "অসীম বোর্ড" আপনি বোঝাচ্ছেন যে সম্পত্তি) তবে এটি কার্যকর হবে।
সাইমন

4
@ সিমন কেউ কি মূল সূত্রটি ব্যাখ্যা করতে পারেন? আমি সহজ শব্দ দিয়ে এটি ব্যাখ্যা করতে সক্ষম হতে
অসুবিধে হচ্ছে

4
@ মারবিবিআই যদি আমরা y = x লাইনের কাছাকাছি থাকে তবে আমরা y = x লাইনের কাছে থেকে প্রতিটি পদক্ষেপে x + y হ্রাস করতে পারি। যদি আমরা y = 0 লাইনের কাছাকাছি হয় তবে আমরা y = 0 লাইনের কাছাকাছি রেখে প্রতিটি পদক্ষেপে x 2 দ্বারা হ্রাস করতে পারি। এ কারণেই আমাদের কাছে ২ টি কেস রয়েছে, আরও নির্দিষ্ট করে এখানে নির্দিষ্ট রেখার কাছাকাছি বলে আমি কী বোঝাতে চাইছি: ১. y = x লাইনের কাছাকাছি বলতে আমি y = x এবং y = x / 2 লাইনের দ্বারা সীমাবদ্ধ বিভাগটি বলেছি (y> ​​x / 2 )। ২. y = 0 লাইনের কাছাকাছি বলতে আমার অর্থ y = 0 এবং y = x / 2 লাইন (y <x / 2) দ্বারা সীমাবদ্ধ section উল্লিখিত সমস্তগুলি গ্রহণ করা এবং যদি আমরা ম্যাথ.ফ্লোর অপসারণ করি এবং প্রধান সূত্রটি সহজ করি তবে আমরা নীচের সূত্রটি পেয়ে যাব: যদি (y> ​​x / 2) তবে {রিটার্ন (x + y) / 3} অন্যথায় x রিটার্ন x / 2}
সাইমন

4
@ সিমন দুর্দান্ত, এটি আরও স্পষ্ট করে তোলে ... আপনার সময়ের জন্য টাই :)
মারবিবিআই

4
কেবলমাত্র, বিএপিসি ২০১201 প্রতিযোগিতারও নাইটস ম্যারাথন নামে একটি প্রশ্ন ছিল একটি অনন্ত বোর্ডে যে এই সূত্রটি একেবারেই সমাধান করে। 2017.bapc.eu/files/preliminaries_problems.pdf
আমির-মৌসভী

19

হ্যাঁ, ডিজকস্ট্রা এবং বিএফএস আপনাকে উত্তরটি দেবে, তবে আমি মনে করি এই সমস্যার দাবা প্রসঙ্গে এমন একটি জ্ঞান সরবরাহ করা যায় যা একটি জেনেরিক সংক্ষিপ্ত-পথ অ্যালগরিদমের চেয়ে বিশেষত একটি অসীম দাবা বোর্ডের চেয়ে দ্রুততর সমাধান দেয় yield

সরলতার জন্য, আসুন দাবা বোর্ডটিকে (x, y) বিমান হিসাবে বর্ণনা করুন। লক্ষ্যটি হ'ল (x0, y0) থেকে (x1, y1) থেকে প্রার্থীর পদক্ষেপগুলি (+ -1, + -2), (+ -2, + -1) এবং (+ -2) ব্যবহার করে সংক্ষিপ্ততম পথটি সন্ধান করা , + -2), প্রশ্নের পিএসে বর্ণিত হিসাবে

নতুন পর্যবেক্ষণটি এখানে: কোণার (x-4, y-4), (x-4, y + 4), (x + 4, y-4), (x + 4, y + 4) সহ একটি স্কোয়ার আঁকুন । এই সেটটিতে (এটিকে এস 4 বলুন) 32 পয়েন্ট রয়েছে। এই 32 টি পয়েন্টের (x, y) এর মধ্যে সবচেয়ে সংক্ষিপ্ত পথের জন্য ঠিক দুটি চলন প্রয়োজন

সেট এস 3 এর 24 পয়েন্টের যে কোনও থেকে সংক্ষিপ্ততম পথ (একইরূপে সংজ্ঞায়িত) (x, y) এর জন্য কমপক্ষে দুটি চাল প্রয়োজন

অতএব, যদি | x1-x0 |> 4 বা | y1-y0 |> 4, (x0, y0) থেকে (x1, y1) পর্যন্ত সংক্ষিপ্ততম পথটি (x0, y0) থেকে সংক্ষিপ্ত পথের চেয়ে দু'টি চলাচল বেশি এস 4 এবং পরবর্তী সমস্যাটি সরাসরি সরল পুনরাবৃত্তির মাধ্যমে দ্রুত সমাধান করা যায়।

এন = সর্বাধিক (| x1-x0 |, | y1-y0 |) আসুন। যদি N> = 4 হয়, তবে (x0, y0) থেকে (x1, y1) সবচেয়ে সংক্ষিপ্ত পথে সিল (N / 2) পদক্ষেপ রয়েছে।


4
এই উত্তর সম্পর্কে আমি কি কেবল বিভ্রান্ত? "কোণার (x-4, y-4), (x-4, y + 4), (x + 4, y-4), (x + 4, y + 4) সহ একটি স্কোয়ার আঁকুন This এটি এস 4) 32 পয়েন্ট রয়েছে "। না এটি হয় না, এটি একটি 9x9 বর্গ হিসাবে 81 থাকে? এছাড়াও, "চলুন এন = সর্বাধিক (| x1-x0 |, | y1-y0 |)। পদক্ষেপ। " এটি সত্য নয়, উদাহরণ হিসাবে ধরুন x0 = 0, y0 = 0, x1 = 4, y1 = 4, সংক্ষিপ্ততম পথটি 4 টি, সূত্রের মতো 2 নয়।
সাটোশি

4
(1) সেটটি কেবল বর্গক্ষেত্রের সীমানার পয়েন্টগুলিকে বোঝায়। এটিতে 32 পয়েন্ট / অবস্থান রয়েছে। (২) যখন আপনি পরিপূরক পদক্ষেপের বিষয়ে পোস্টারের পিএস বিবেচনা করেন (মূল পোস্টে মন্তব্যগুলিও দেখুন), ন্যূনতম পদক্ষেপের সংখ্যা দুটি হয়ে যায়।
স্টিভ তেজোয়া

ধন্যবাদ, এটি এখন উপলব্ধি করে :)
satoshi

একটি বোর্ড যদি অসীম হয়?
এক্ষেত্রে কেবল বিএফএসই

@ স্টেটিজোয়া দুঃখিত, আপনি কেন (+ -2, + -2) পদক্ষেপের কথা উল্লেখ করেছেন তা আমি বুঝতে পারি না, কারণ এটি নাইটের পক্ষে অসম্ভব
পাভেল বেলি

12

ও (1) উত্তর উপরে [ https://stackoverflow.com/a/8778592/4288232 মোস্তফা সর্দার Şanlı দ্বারা ] সত্যিই কাজ করছে না। ((1,1) বা (3,2) বা (4,4), (1,0) বা (2,2%) এর সুস্পষ্ট প্রান্তের ক্ষেত্রে আলাদা করুন।

নীচে একটি খুব কৃপণ সমাধান (পাইথন) দেওয়া হয়েছে, যা কাজ করে (যুক্ত "পরীক্ষাগুলি সহ"):

def solve(x,y):
        x = abs(x)
        y = abs(y)
        if y > x:
            temp=y
            y=x
            x=temp  
        if (x==2 and y==2):
            return 4
        if (x==1 and y==0):
            return 3

    if(y == 0 or float(y) / float(x) <= 0.5):
        xClass = x % 4
        if (xClass == 0):
            initX = x/2
        elif(xClass == 1):
            initX = 1 + (x/2)
        elif(xClass == 2):
            initX = 1 + (x/2)
        else:
            initX = 1 + ((x+1)/2)

        if (xClass > 1):
            return initX - (y%2)
        else:
            return initX + (y%2)
    else:
        diagonal = x - ((x-y)/2)
        if((x-y)%2 == 0):
            if (diagonal % 3 == 0):
                return (diagonal/3)*2
            if (diagonal % 3 == 1):
                return ((diagonal/3)*2)+2
            else:
                return ((diagonal/3)*2)+2
        else:
            return ((diagonal/3)*2)+1


def test():
    real=[
    [0,3,2,3,2,3,4,5,4,5,6,7,6,7],
    [3,2,1,2,3,4,3,4,5,6,5,6,7,8],
    [2,1,4,3,2,3,4,5,4,5,6,7,6,7],
    [3,2,3,2,3,4,3,4,5,6,5,6,7,8],
    [2,3,2,3,4,3,4,5,4,5,6,7,6,7],
    [3,4,3,4,3,4,5,4,5,6,5,6,7,8],
    [4,3,4,3,4,5,4,5,6,5,6,7,6,7],
    [5,4,5,4,5,4,5,6,5,6,7,6,7,8],
    [4,5,4,5,4,5,6,5,6,7,6,7,8,7],
    [5,6,5,6,5,6,5,6,7,6,7,8,7,8],
    [6,5,6,5,6,5,6,7,6,7,8,7,8,9],
    [7,6,7,6,7,6,7,6,7,8,7,8,9,8]]

    for x in range(12):
        for y in range(12):
            res = solve(x,y)
            if res!= real[x][y]:
                print (x, y), "failed, and returned", res, "rather than", real[x][y]
            else:
               print (x, y), "worked. Cool!"

test()

10
উত্তর হিসাবে উল্লেখ করে aboveবা belowসত্যই কাজ করে না।
পেট্র পেলার

4
পাইথন 2/3 এ আমার সংস্করণটি এখানে। আমি সমাধানের কাজটি সহজ করার চেষ্টা করেছি কিন্তু এটি সহজ নয়! gist.github.com/TimSC/8b9a80033f3a22a708a4b9741931c591
টিএমএসসি

9

আপনার যা করা দরকার তা হ'ল নাইটের সম্ভাব্য চালগুলি গ্রাফ হিসাবে ভাবুন, যেখানে বোর্ডের প্রতিটি অবস্থান নোড এবং একটি প্রান্ত হিসাবে অন্যান্য অবস্থানে সম্ভাব্য পদক্ষেপগুলি। ডিজকস্ট্রার অ্যালগরিদমের কোনও প্রয়োজন নেই, কারণ প্রতিটি প্রান্তের ওজন বা দূরত্ব একই থাকে (এগুলি সবই করা সহজ বা সংক্ষিপ্ত)। আপনি শেষ অবস্থানে পৌঁছানো অবধি আপনার প্রারম্ভিক বিন্দু থেকে একটি বিএফএস অনুসন্ধান করতে পারেন।


4
+ !, এই নির্দিষ্ট সমস্যার জন্য বিএফএস যথেষ্ট।
টিয়ানশু

4
বিএফএস যথেষ্ট হতে পারে, তবে একটি সরল বিএসটি অনেকগুলি প্রশ্নের উদ্রেক করবে - আপনি কোন স্কোয়ারে গিয়েছেন তা ক্যাশে করতে হবে। এবং তারপরে বিএফএস কিছুটা ডিজকস্ট্রার অ্যালগরিদমের মতো দেখতে শুরু করেছে ...
চার্লস স্টুয়ার্ট

আমরা ইতিমধ্যে যে সমস্ত অবস্থানটি ভ্রমণ করেছি তার ট্র্যাক করার সর্বোত্তম উপায় কী হবে যাতে বিএফএস ট্রি কেবল এগিয়ে যায় এবং যখন আমরা একটি নতুন বিন্দু থেকে উপলব্ধ নোডগুলি আবিষ্কার করি তখন আমরা পুরানো নোডটি আবার যুক্ত করব না ... এবং আটকে যাব অসীম লুপ!
নীতীশ উপ্রেতি

আমি এখানে মনে করি যে আমরা আমাদের শেষ নাইটের অবস্থানটি সংরক্ষণ করে করতে পারি?
নীতীশ উপ্রেতি

7

পাইথনে প্রথম নীতিগুলি থেকে সমাধান

কোডলিটি পরীক্ষায় আমি প্রথম এই সমস্যার মুখোমুখি হয়েছি। এটি সমাধানের জন্য তারা আমাকে 30 মিনিট সময় দিয়েছিল - এই ফলাফলটি পেতে আমার চেয়ে অনেক বেশি সময় লেগেছে! সমস্যাটি ছিল: 0,0 থেকে x এ যাওয়ার জন্য নাইটের জন্য কতগুলি চালনা লাগে, কেবলমাত্র নাইট নাইটের চালগুলি ব্যবহার করে। এক্স এবং ওয়াই কম বা কম আনবাউন্ডেড ছিল (তাই আমরা এখানে একটি সাধারণ 8x8 দাবাবোর্ডের কথা বলছি না)।

তারা একটি ও (1) সমাধান চেয়েছিল। আমি একটি সমাধান চাইছিলাম যেখানে প্রোগ্রামটি স্পষ্টতই সমস্যার সমাধান করছিল (যেমন আমি গ্রামের প্যাটার্নের চেয়ে আরও স্পষ্টতই কিছু চেয়েছিলাম - নিদর্শনগুলি যেখানে আপনি দেখছেন না সেখানে ভেঙে ফেলার অভ্যাস রয়েছে) এবং আমি সত্যিই কোনও বিষয়ের উপর নির্ভর না করতে চাইতাম মোস্তফার সলিউশনে যেমন নিরক্ষিত সূত্র

সুতরাং, এটি আমার মূল্য সমাধানের জন্য এটি সমাধান। অন্যদের মতো সমাধানটি অক্ষ এবং ত্রিভুজগুলির প্রতিসাম্য হিসাবে চিহ্নিত করে শুরু করুন, সুতরাং আমাদের কেবল 0> = y> = x এর জন্য সমাধান করতে হবে। সরলতার জন্য ব্যাখ্যা (এবং কোড) আমি সমস্যার বিপরীতে যাচ্ছি: নাইটটি x, y থেকে শুরু হয় এবং 0,0 এর লক্ষ্য রেখে চলেছে।

ধরা যাক আমরা উত্সের আশেপাশে সমস্যাটি সঙ্কুচিত করি। যথাযথভাবে 'ভাস্কিন্টি' এর অর্থ কী তা আমরা পেয়ে যাব, তবে আপাতত, আসুন কেবল একটি চিটশিটে (নীচে বামদিকে উত্স) কিছু সমাধান লিখি:

2 1 4 3
3 2 1 2
0 3 2 3

সুতরাং, গ্রিডে x, y দেওয়া, আমরা কেবল উত্সে চলে আসার সংখ্যাটি পড়তে পারি।

যদি আমরা গ্রিডের বাইরে শুরু করে থাকি তবে আমাদের এটির দিকে ফিরে যেতে আমাদের কাজ করতে হবে। আমরা 'মিডলাইন' প্রবর্তন করি যা y = x / 2 দ্বারা প্রতিনিধিত্ব করা লাইন is এই লাইনের এক্স, ওয়াইয়ের যে কোনও নাইট 8 টায় চালানোর সিরিজ (যা: (-2, -1)) এর সাহায্যে চিটশিটে ফিরে যাওয়ার পথে কাজ করতে পারে। যদি এক্স, ওয়াই মিডলাইনের উপরে থাকে তবে আমাদের আটটা বা o'clock টা বাজে পদক্ষেপের উত্তরসূরি প্রয়োজন এবং এটি যদি মিডলাইনের নীচে থাকে তবে আমাদের আটটা বা দশ মিনিটের উত্তরাধিকার প্রয়োজন 'ঘড়ি চলে। এখানে দুটি বিষয় লক্ষণীয়:

  • এই সিকোয়েন্সগুলি সম্ভাব্য সংক্ষিপ্ততম পাথ। (আমাকে এটি প্রমাণ করতে চান, না এটি সুস্পষ্ট?)
  • আমরা কেবল এই ধরণের পদক্ষেপের সংখ্যা সম্পর্কে যত্নশীল। আমরা যেকোন ক্রমে চলনগুলি মিক্স এবং মেলাতে পারি।

সুতরাং, আসুন উপরের মিডলাইন মুভগুলি দেখুন। আমরা যা দাবি করছি তা হ'ল:

  • (dx; dy) = (2,1; 1,2) (n8; n7) (ম্যাট্রিক্স স্বরলিপি, গণিতের টাইপসেটিং ছাড়াই - কলাম ভেক্টর (dx; dy) বর্গক্ষেত্রের মেট্রিক্স সমান কলাম ভেক্টর (n8; n7) দ্বারা গুণিত - 8 টা বাজে চালনার সংখ্যা এবং 7 টা বাঘের সংখ্যা) এবং একইভাবে;

  • (dx; dy) = (2,2; 1, -1) (n8; n10)

আমি দাবি করছি যে dx, dy মোটামুটিভাবে (x, y) হবে, সুতরাং (x-dx, y-dy) উত্সের কাছাকাছি থাকবে (যাই হোক না কেন 'সান্নিধ্য' পরিণত হবে)।

এই শর্তগুলি গণনা করে কোডের দুটি লাইনই এর সমাধান, তবে সেগুলি কয়েকটি দরকারী বৈশিষ্ট্য হিসাবে বেছে নেওয়া হয়েছে:

  • উপরের মিডলাইন সূত্রটি (x, y) একটি (0,0), (1,1), বা (2,2) এ চলে যায়।
  • নীচের মিডলাইন সূত্রটি (x, y) এক (0,0), (1,0), (2,0), বা (1,1) এ চলে যায় 1,

(আপনি কি এর প্রমাণ চান?) সুতরাং, নাইটের দূরত্বটি n7, n8, n10 এবং চিটশিট [x-dx, y-dy] এর যোগফল হবে এবং আমাদের চিটশিট এটি হ্রাস করে:

. . 4
. 2 .
0 3 2

এখন, এটি গল্পের একেবারে শেষ নয়। নীচের সারিতে 3 টি দেখুন। আমরা কেবল এটির কাছে পৌঁছাতে পারছি:

  • আমরা সেখানে শুরু, বা
  • আমরা 8 টা এবং 10 টা বেজে যাওয়ার ক্রম অনুসারে সেখানে চলে এসেছি। তবে যদি শেষ পদক্ষেপটি রাত ৮ টা বাজে (যা এটি হবার অধিকারযুক্ত, যেহেতু আমরা যে কোনও ক্রমে আমাদের চালচলন করতে পারি), তবে আমাদের অবশ্যই (৩,১) পেরিয়ে যেতে হবে, যার দূরত্ব আসলে ২ (আপনি যেমন পারেন তেমন) আসল চিটশিট থেকে দেখুন)। সুতরাং আমাদের যা করা উচিত তা হ'ল এক 8 বাজে পদক্ষেপটি, মোট দুটি চাল দুটি সঞ্চয় করে।

উপরের ডানদিকে 4 এর সাথে একই রকম অপটিমাইজেশন রয়েছে। সেখানে শুরু করা ছাড়াও পৌঁছানোর একমাত্র রাস্তাটি (4,3) থেকে 8 টার দিকে যেতে হবে। এটি চিটশিটে নয়, তবে এটি যদি থাকত তবে এর দূরত্ব 3 হবে, কারণ আমরা এর পরিবর্তে 7 টি আটকে থাকতে পারি (3,1), যার কেবল মাত্র 2 এর দূরত্ব রয়েছে So সুতরাং, আমাদের একটিটিকে ব্যাক-ট্র্যাক করা উচিত 8-বাজেটি সরান, এবং তারপরে একটি 7-pm এগিয়ে যান।

সুতরাং, আমাদের চিটশিটে আরও একটি নম্বর যুক্ত করতে হবে:

. . 4
. 2 . 2
0 3 2

(দ্রষ্টব্য: (0,1) এবং (0,2) থেকে ব্যাক-ট্র্যাকিং অপটিমাইজেশনের পুরো লোড রয়েছে তবে যেহেতু সলভার কখনও আমাদের সেখানে নিয়ে যাবেন না, সেগুলি সম্পর্কে আমাদের চিন্তা করার দরকার নেই))

সুতরাং এখানে তাই এখানে মূল্যায়নের জন্য পাইথন কোডের কিছু:

def knightDistance (x, y):
    # normalise the coordinates
    x, y = abs(x), abs(y)
    if (x<y): x, y = y, x
    # now 0 <= y <= x

    # n8 means (-2,-1) (8 o'clock), n7 means (-1,-2) (7 o'clock), n10 means (-2,+1) (10 o'clock)
    if (x>2*y):
        # we're below the midline.  Using 8- & 10-o'clock moves
        n7, n8, n10 = 0,  (x + 2*y)//4,  (x - 2*y + 1)//4
    else:
        # we're above the midline.  Using 7- and 8-o'clock moves
        n7, n8, n10 = (2*y - x)//3, (2*x - y)//3,  0
    x -= 2*n8 + n7 + 2*n10
    y -= n8 + 2*n7 - n10
    # now 0<=x<=2, and y <= x.  Also (x,y) != (2,1)

    # Try to optimise the paths.
    if (x, y)==(1, 0): # hit the  3.  Did we need to?
        if (n8>0): # could have passed through the 2 at 3,1.  Back-up
            x, y = 3, 1; n8-=1;
    if (x, y)==(2, 2): # hit the 4.  Did we need to?
        if (n8>0): # could have passed through a 3 at 4,3.  Back-up, and take 7 o'clock to 2 at 3,1
            x, y = 3, 1; n8-=1; n7+=1

    # Almost there.  Now look up the final leg
    cheatsheet = [[0, 3, 2], [2, None, 2], [4]]
    return n7 + n8 + n10 + cheatsheet [y][x-y]

ঘটনাক্রমে, আপনি যদি কোনও আসল রুট জানতে চান, তবে এই অ্যালগরিদম এটিও সরবরাহ করে: এটি কেবল n7 7-pm চলনের উত্তরসূরি, তারপরে (বা ছেদ করা) n8 8-pm চলন, n10 10- বেলা সাড়ে ১১ টায় চলে যায় এবং চিটশীট দ্বারা নির্ধারিত যে কোনও নাচ (যা নিজেই চিটশিটে থাকতে পারে)।

এখন: কীভাবে এটি প্রমাণ করা যায় ঠিক। সঠিক ফলাফলের সারণির সাথে এই ফলাফলগুলির তুলনা করা যথেষ্ট নয়, কারণ সমস্যাটি নিজেই সীমাহীন। তবে আমরা এটি বলতে পারি যে, যদি নাইটের বর্গাকার s এর দূরত্ব d হয় তবে যদি {m s s থেকে আইনী পদক্ষেপের সেট হয় তবে নাইটের দূরত্ব (s + m) হয় ডি -1 বা ডি + 1 হতে হবে সব মি। (আপনার কি এর প্রমাণ দরকার?) তদ্ব্যতীত, কমপক্ষে এমন একটি বর্গ অবশ্যই থাকতে হবে যার দূরত্ব ডি -1, যদি না এর উত্স হয়। সুতরাং, আমরা এই সম্পত্তিটি প্রতিটি স্কোয়ারের জন্য ধারণ করে সঠিকতা প্রমাণ করতে পারি। এইভাবে:

def validate (n):

    def isSquareReasonable (x, y):
        d, downhills = knightDistance (x, y), 0
        moves = [(1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1), (-1,  2)]
        for dx, dy in moves:
            dd = knightDistance (x+dx,  y+dy)
            if (dd == d+1): pass
            elif (dd== d-1): downhills += 1
            else: return False;
        return (downhills>0) or (d==0)

    for x in range (0,  n+1):
        for y in range (0,  n+1):
            if not isSquareReasonable (x,  y): raise RuntimeError ("Validation failed")

বিকল্পভাবে, আমরা উতর থেকে উতর পর্যন্ত রুটটি অনুসরণ করে যে কোনও একটি বর্গের নির্ভুলতা প্রমাণ করতে পারি। প্রথমে উপরের মতো যুক্তিসঙ্গততার জন্য s পরীক্ষা করুন, তারপরে যে কোনও এস + মিটারের দূরত্ব (গুলি + মি) == ডি -1 নির্বাচন করুন। আমরা উত্স পৌঁছানো পর্যন্ত পুনরাবৃত্তি।

হাওযাত?


2
/*
This program takes two sets of cordinates on a 8*8 chessboard, representing the
starting and ending points of a knight's path.
The problem is to print the cordinates that the knight traverses in between, following
the shortest path it can take.
Normally this program is to be implemented using the Djikstra's algorithm(using graphs)
but can also be implemented using the array method.
NOTE:Between 2 points there may be more than one shortest path. This program prints
only one of them.
*/

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

int m1=0,m2=0;

/*
This array contains three columns and 37 rows:
The rows signify the possible coordinate differences.
The columns 1 and 2 contains the possible permutations of the row and column difference 
between two positions on a chess board;
The column 3 contains the minimum number of steps involved in traversing the knight's 
path with the given permutation*/

int arr[37][3]={{0,0,0},{0,1,3},{0,2,2},{0,3,3},{0,4,2},{0,5,3},{0,6,4},{0,7,5},    {1,1,2},{1,2,1},{1,3,2},{1,4,3},{1,5,4},{1,6,3},{1,7,4},{2,2,4},{2,3,3},{2,4,2},
            {2,5,3},{2,6,3},{2,7,5},{3,3,2},{3,4,3},{3,5,4},{3,6,3},{3,7,4},{4,4,4},{4,5,3},{4,6,4},{4,7,5},{5,5,4},{5,6,5},{5,7,4},{6,6,5},{6,7,5},{7,7,6}};

void printMoves(int,int,int,int,int,int);
void futrLegalMove(int,int,int,int);
main()
{
  printf("KNIGHT'S SHORTEST PATH ON A 8*8 CHESSBOARD :\n");
  printf("------------------------------------------");
  printf("\nThe chessboard may be treated as a 8*8 array here i.e. the (1,1) ");
  printf("\non chessboard is to be referred as (0,0) here and same for (8,8) ");
  printf("\nwhich is to be referred as (7,7) and likewise.\n");
  int ix,iy,fx,fy;
  printf("\nEnter the initial position of the knight :\n");
  scanf("%d%d",&ix,&iy);
  printf("\nEnter the final position to be reached :\n");
  scanf("%d%d",&fx,&fy);
  int px=ix,py=iy;
  int temp;
  int tx,ty;
  printf("\nThe Knight's shortest path is given by :\n\n");
  printf("(%d, %d)",ix,iy);
  futrLegalMove(px,py,m1,m2);
  printMoves(px,py,fx,fy,m1,m2);
   getch();
} 

/*
  This method checkSteps() checks the minimum number of steps involved from current
  position(a & b) to final position(c & d) by looking up in the array arr[][].
*/

int checkSteps(int a,int b,int c,int d)
{  
    int xdiff, ydiff;
    int i, j;
    if(c>a)
        xdiff=c-a;
    else
        xdiff=a-c;
    if(d>b)
        ydiff=d-b;
    else
        ydiff=b-d;
    for(i=0;i<37;i++)
        {
            if(((xdiff==arr[i][0])&&(ydiff==arr[i][1])) || ((xdiff==arr[i][1])&& (ydiff==arr[i] [0])))
            {
                j=arr[i][2];break;
            }
        }

        return j;
}   

/*
This method printMoves() prints all the moves involved.
*/

void printMoves(int px,int py, int fx, int fy,int a,int b)
{    
 int temp;
 int tx,ty;
 int t1,t2;
  while(!((px==fx) && (py==fy)))
  {   
      printf(" --> ");
      temp=checkSteps(px+a,py+b,fx,fy);
      tx=px+a;
      ty=py+b;
      if(!(a==2 && b==1))
      {if((checkSteps(px+2,py+1,fx,fy)<temp) && checkMove(px+2,py+1))
      {temp=checkSteps(px+2,py+1,fx,fy);
       tx=px+2;ty=py+1;}}
      if(!(a==2 && b==-1))
      {if((checkSteps(px+2,py-1,fx,fy)<temp) && checkMove(px+2,py-1))
      {temp=checkSteps(px+2,py-1,fx,fy);
       tx=px+2;ty=py-1;}}
      if(!(a==-2 && b==1))
      {if((checkSteps(px-2,py+1,fx,fy)<temp) && checkMove(px-2,py+1))
      {temp=checkSteps(px-2,py+1,fx,fy);
       tx=px-2;ty=py+1;}}
      if(!(a==-2 && b==-1))
      {if((checkSteps(px-2,py-1,fx,fy)<temp) && checkMove(px-2,py-1))
      {temp=checkSteps(px-2,py-1,fx,fy);
       tx=px-2;ty=py-1;}}
      if(!(a==1 && b==2))
      {if((checkSteps(px+1,py+2,fx,fy)<temp) && checkMove(px+1,py+2))
      {temp=checkSteps(px+1,py+2,fx,fy);
       tx=px+1;ty=py+2;}}
      if(!(a==1 && b==-2))
      {if((checkSteps(px+1,py-2,fx,fy)<temp) && checkMove(px+1,py-2))
      {temp=checkSteps(px+1,py-2,fx,fy);
       tx=px+1;ty=py-2;}}
      if(!(a==-1 && b==2))
      {if((checkSteps(px-1,py+2,fx,fy)<temp) && checkMove(px-1,py+2))
      {temp=checkSteps(px-1,py+2,fx,fy);
       tx=px-1;ty=py+2;}}
      if(!(a==-1 && b==-2))
      {if((checkSteps(px-1,py-2,fx,fy)<temp) && checkMove(px-1,py-2))
      {temp=checkSteps(px-1,py-2,fx,fy);
       tx=px-1;ty=py-2;}}
       t1=tx-px;//the step taken in the current move in the x direction.
       t2=ty-py;//" " " " " " " " " " " " " " " " " " " " " y " " " " ".
       px=tx;
       py=ty;
       printf("(%d, %d)",px,py);
       futrLegalMove(px,py,t1,t2);
       a=m1;
       b=m2;
   }

} 

/*
The method checkMove() checks whether the move in consideration is beyond the scope of
board or not.
*/   

int checkMove(int a, int b)
{
    if(a>7 || b>7 || a<0 || b<0)
        return 0;
    else
        return 1;
}

/*Out of the 8 possible moves, this function futrLegalMove() sets the valid move by
  applying the following constraints
      1. The next move should not be beyond the scope of the board.
      2. The next move should not be the exact opposite of the previous move.
  The 1st constraint is checked by sending all possible moves to the checkMove() 
  method;
  The 2nd constraint is checked by passing as parameters(i.e. a and b) the steps of the 
  previous move and checking whether or not it is the exact opposite of the current move.
*/

void futrLegalMove(int px,int py,int a,int b)
{
     if(checkMove(px+2,py+1) && (a!=-2 && b!=-1))
         m1=2,m2=1;
     else
     {
         if(checkMove(px+2,py-1)&& (a!=-2 && b!=1))
             m1=2,m2=-1;
     else
     {
         if(checkMove(px-2,py+1)&& (a!=2 && b!=-1))
              m1=-2,m2=1;
     else
     {
         if(checkMove(px-2,py-1)&& (a!=2 && b!=1))
               m1=-2,m2=-1;
     else
     {
         if(checkMove(px+1,py+2)&& (b!=-2 && a!=-1))
               m2=2,m1=1;
     else
     {
         if(checkMove(px+1,py-2)&& (a!=-1 && b!=2))
               m2=-2,m1=1;
     else
     {
         if(checkMove(px-1,py+2)&& (a!=1 && b!=-2))
               m2=2,m1=-1;
     else
     {
         if(checkMove(px-1,py-2)&& (a!=1 && b!=2))
               m2=-2,m1=-1;
     }}}}}}}
}

//End of Program.

আমি গ্রাফগুলি এখনও অধ্যয়ন করি নি ... কেবল এটির মাধ্যমে এটি প্রয়োগ করার সমস্যা অনুসারে, আমি এগুলি ব্যতীত অন্য কোনও সমাধান বের করতে পারিনি। আমি অবস্থানগুলি র‍্যাঙ্ক এবং ফাইল হিসাবে দেখি না (সাধারণ দাবা চিহ্নিতকরণ), তবে অ্যারে সূচক হিসাবে। এফওয়াইআই, এটি কেবল 8 * 8 দাবাবোর্ডের জন্য। যে কোনও উন্নতির পরামর্শ সর্বদা স্বাগত জানানো হয়।

* মন্তব্যগুলি আপনার যুক্তি বোঝার জন্য যথেষ্ট should তবে আপনি সবসময় জিজ্ঞাসা করতে পারেন।

* ডিইভি-সি ++ ৪.৯.৯.২ সংকলক (রক্তপাত সফ্টওয়্যার) পরীক্ষা করা হয়েছে।


2

আমি মনে করি এটি হয়ত আপনাকে সাহায্য করবে ..

NumWays(x,y)=1+min(NumWays(x+-2,y-+1),NumWays(x+-1,y+-2)); 

এবং সমাধান পেতে ডায়নামিক প্রোগ্রামিং ব্যবহার করে।

পিএস: এটি গ্রাফের নোড এবং প্রান্তগুলি ঘোষণার ঝামেলা ছাড়াই বিএফএস ব্যবহার করে।


1

পার্লে প্রয়োগ করা এই বিশেষ সমস্যার সমাধান এখানে। এটি একটি সংক্ষিপ্ততম পথ দেখায় - কিছু ক্ষেত্রে একের বেশি হতে পারে।

আমি উপরে বর্ণিত কোনও অ্যালগরিদম ব্যবহার করি নি - তবে এটি অন্যান্য সমাধানগুলির সাথে তুলনা করে ভাল লাগবে।

#!/usr/local/bin/perl -w

use strict;

my $from = [0,0];
my $to   = [7,7];

my $f_from = flat($from);
my $f_to   = flat($to);

my $max_x = 7;
my $max_y = 7;
my @moves = ([-1,2],[1,2],[2,1],[2,-1],[1,-2],[-1,-2],[-2,-1],[-2,1]);
my %squares = ();
my $i = 0;
my $min = -1;

my @s = ( $from );

while ( @s ) {

   my @n = ();
   $i++;

   foreach my $s ( @s ) {
       unless ( $squares{ flat($s) } ) {
            my @m = moves( $s );
            push @n, @m;
            $squares{ flat($s) } = { i=>$i, n=>{ map {flat($_)=>1} @m }, };

            $min = $i if $squares{ flat($s) }->{n}->{$f_to};
       }
   }

   last if $min > -1;
   @s = @n;
}

show_path( $f_to, $min );

sub show_path {
    my ($s,$i) = @_;

    return if $s eq $f_from;

    print "$i => $f_to\n" if $i == $min;

    foreach my $k ( keys %squares ) {
       if ( $squares{$k}->{i} == $i && $squares{$k}->{n}->{$s} ) {
            $i--;
            print "$i => $k\n";
            show_path( $k, $i );
            last;
       }
    }
}

sub flat { "$_[0]->[0],$_[0]->[1]" }

sub moves {
    my $c = shift;
    my @s = ();

    foreach my $m ( @moves ) {
       my $x = $c->[0] + $m->[0];
       my $y = $c->[1] + $m->[1];

       if ( $x >= 0 && $x <=$max_x && $y >=0 && $y <=$max_y) {
           push @s, [$x, $y];
       }
    }
    return @s;
}

__END__

1
public class Horse {

    private int[][] board;
    private int[] xer = { 2, 1, -1, -2, -2, -1, 1, 2 };
    private int[] yer = { 1, 2, 2, 1, -1, -2, -2, -1 };
    private final static int A_BIG_NUMBER = 10000;
    private final static int UPPER_BOUND = 64;


    public Horse() {
        board =  new int[8][8];
    }

    private int solution(int x, int y, int destx, int desty, int move) {

        if(move == UPPER_BOUND) {
            /* lets put an upper bound to avoid stack overflow */
            return A_BIG_NUMBER;
        }

        if(x == 6 && y ==5) {
            board[6][5] = 1;
            return 1;
        }
        int min = A_BIG_NUMBER;
        for (int i = 0 ; i < xer.length; i++) {
            if (isMoveGood(x + xer[i], y + yer[i])) {
                if(board[x + xer[i]][y + yer[i]] != 0) {
                    min = Integer.min(min, 1 + board[x +xer[i]] [y +yer[i]]);                   
                } else {
                    min = Integer.min(min, 1 + solution(x + xer[i], y + yer[i], destx, desty, move + 1));   
                }                   
            }
        }   
        board[x][y] = min;
        return min;
    }


    private boolean isMoveGood(int x, int y) {
        if (x >= 0 && x < board.length && y >= 0 && y < board.length)
            return true;
        return false;
    }


    public static void main(String[] args) {

        int destX = 6;
        int destY = 7;
        final Horse h = new Horse();
        System.out.println(h.solution(0, 0, destX, destY, 0));
    }
}

0

উপরের গ্রীম পাইলের উত্তরের জসফিডাল থেকে কেবল রুবি কোড , সমস্ত অতিরিক্ত কোডটি স্ট্রিপ করে এবং তার অ্যালগরিদমের দ্বারা সমাধান পেতে কেবল রুবিতে রূপান্তরিত হয়েছে, মনে হচ্ছে এটি কাজ করছে। এখনও পরীক্ষা হচ্ছে:

def getBoardOffset(board)
  return board.length / 2
end

def setMoveCount(x, y, count, board)
  offset = getBoardOffset(board)
  board[y + offset][x + offset] = count
end

def getMoveCount(x, y, board)
    offset = getBoardOffset(board)
    row = board[y + offset]
    return row[x + offset]
end

def isBottomOfVerticalCase(x, y)
    return (y - 2 * x) % 4 == 0
end

def isPrimaryDiagonalCase(x, y)
    return (x + y) % 2 == 0
end

def isSecondaryDiagonalCase(x, y)
    return (x + y) % 2 == 1
end

def simplifyBySymmetry(x, y)
    x = x.abs
    y = y.abs
    if (y < x)
      t = x
      x = y
      y = t
    end
    return {x: x, y: y}
end

def getPrimaryDiagonalCaseMoveCount(x, y)
    var diagonalOffset = y + x
    var diagonalIntersect = diagonalOffset / 2
    return ((diagonalIntersect + 2) / 3).floor * 2
end

def getSpecialCaseMoveCount(x, y)
    specials = [{
            x: 0,
            y: 0,
            d: 0
        },
        {
            x: 0,
            y: 1,
            d: 3
        },
        {
            x: 0,
            y: 2,
            d: 2
        },
        {
            x: 0,
            y: 3,
            d: 3
        },
        {
            x: 2,
            y: 2,
            d: 4
        },
        {
            x: 1,
            y: 1,
            d: 2
        },
        {
            x: 3,
            y: 3,
            d: 2
        }
    ];
    matchingSpecial=nil
    specials.each do |special|
      if (special[:x] == x && special[:y] == y)
        matchingSpecial = special
      end
    end
    if (matchingSpecial)
      return matchingSpecial[:d]
    end
end

def isVerticalCase(x, y)
  return y >= 2 * x
end

def getVerticalCaseMoveCount(x, y)
    normalizedHeight = getNormalizedHeightForVerticalGroupCase(x, y)
    groupIndex = (normalizedHeight/4).floor
    groupStartMoveCount = groupIndex * 2 + x
    return groupStartMoveCount + getIndexInVerticalGroup(x, y)
end

def getIndexInVerticalGroup(x, y)
    return getNormalizedHeightForVerticalGroupCase(x, y) % 4
end

def getYOffsetForVerticalGroupCase(x) 
    return x * 2
end

def getNormalizedHeightForVerticalGroupCase(x, y)
    return y - getYOffsetForVerticalGroupCase(x)
end

def getSecondaryDiagonalCaseMoveCount(x, y)
    diagonalOffset = y + x
    diagonalIntersect = diagonalOffset / 2 - 1
    return ((diagonalIntersect + 2) / 3).floor * 2 + 1
end

def getMoveCountO1(x, y)
    newXY = simplifyBySymmetry(x, y)
    x = newXY[:x]
    y = newXY[:y]
    specialMoveCount = getSpecialCaseMoveCount(x ,y)
    if (specialMoveCount != nil)
      return specialMoveCount
    elsif (isVerticalCase(x, y))
      return getVerticalCaseMoveCount(x ,y)
    elsif (isPrimaryDiagonalCase(x, y))
      return getPrimaryDiagonalCaseMoveCount(x ,y)
    elsif (isSecondaryDiagonalCase(x, y))
      return getSecondaryDiagonalCaseMoveCount(x ,y)
    end
end

def solution(x ,y)
  return getMoveCountO1(x, y)
end


puts solution(0,0)

যদি কারও পূর্ণ কোডের প্রয়োজন হয় তবে কাউকে কিছুটা সময় রূপান্তরকারী কোড সংরক্ষণ করা কেবলমাত্র উদ্দেশ্য।


0

এখানে জুলস মেয়ের ফাংশনের পিএইচপি সংস্করণ

function knightDistance($x, $y)
{
    $x = abs($x);
    $y = abs($y);

    if($x < $y)
    {
        $tmp = $x;
        $x = $y;
        $y = $tmp;
    }

    if($x > 2 * $y)
    {
        $n7 = 0;
        $n8 = floor(($x + 2*$y) / 4);
        $n10 = floor(($x - 2*$y +1) / 4);
    }
    else
    {
        $n7 = floor((2*$y - $x) / 3);
        $n8 = floor((2*$x - $y) / 3);
        $n10 = 0;
    }

    $x -= 2 * $n8 + $n7 + 2 * $n10;
    $y -= $n8 + 2 * $n7 - $n10;

    if($x == 1 && $y == 0)
    {
        if($n8 > 0)
        {
            $x = 3;
            $y = 1;
            $n8--;
        }
    }
    if($x == 2 && $y == 2)
    {
        if($n8 > 0)
        {
            $x = 3;
            $y = 1;
            $n8--;
            $n7++;
        }
    }

    $cheatsheet = [[0, 3, 2], [2, 0, 2], [4]];

    return $n7 + $n8 + $n10 + $cheatsheet [$y][$x-$y];
}

0

এখানে আমার প্রোগ্রাম। এটি একটি নিখুঁত সমাধান নয়। পুনরাবৃত্তি ফাংশন করতে প্রচুর পরিবর্তন আছে। তবে এই শেষ ফলাফলটি নিখুঁত। আমি কিছুটা অপ্টিমাইজ করার চেষ্টা করেছি।

public class KnightKing2 {
    private static int tempCount = 0;

    public static void main(String[] args) throws IOException {
        Scanner in = new Scanner(System.in);
        int ip1 = Integer.parseInt(in.nextLine().trim());
        int ip2 = Integer.parseInt(in.nextLine().trim());
        int ip3 = Integer.parseInt(in.nextLine().trim());
        int ip4 = Integer.parseInt(in.nextLine().trim());
        in.close();
        int output = getStepCount(ip1, ip2, ip3, ip4);
        System.out.println("Shortest Path :" + tempCount);

    }

    // 2 1 6 5 -> 4
    // 6 6 5 5 -> 2

    public static int getStepCount(int input1, int input2, int input3, int input4) {
        return recurse(0, input1, input2, input3, input4);

    }

    private static int recurse(int count, int tx, int ty, int kx, int ky) {

        if (isSolved(tx, ty, kx, ky)) {
            int ccount = count+1;
            System.out.println("COUNT: "+count+"--"+tx+","+ty+","+ccount);
            if((tempCount==0) || (ccount<=tempCount)){
                tempCount = ccount;
            }
            return ccount;
        }

            if ((tempCount==0 || count < tempCount) && ((tx < kx+2) && (ty < ky+2))) {
                if (!(tx + 2 > 8) && !(ty + 1 > 8)) {
                    rightTop(count, tx, ty, kx, ky);

                }
                if (!(tx + 2 > 8) && !(ty - 1 < 0)) {
                    rightBottom(count, tx, ty, kx, ky);
                }
                if (!(tx + 1 > 8) && !(ty + 2 > 8)) {
                    topRight(count, tx, ty, kx, ky);
                }
                if (!(tx - 1 < 0) && !(ty + 2 > 8)) {
                    topLeft(count, tx, ty, kx, ky);
                }
                if (!(tx + 1 > 8) && !(ty - 2 < 0)) {
                     bottomRight(count, tx, ty, kx, ky);
                }
                if (!(tx - 1 < 0) && !(ty - 2 < 0)) {
                     bottomLeft(count, tx, ty, kx, ky);
                }
                if (!(tx - 2 < 0) && !(ty + 1 > 8)) {
                    leftTop(count, tx, ty, kx, ky);
                }
                if (!(tx - 2 < 0) && !(ty - 1 < 0)) {
                    leftBottom(count, tx, ty, kx, ky);
                }
            }

        return count;

    }

    private static int rightTop(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx + 2, ty + 1, kx, ky);

    }

    private static int topRight(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx + 1, ty + 2, kx, ky);
    }

    private static int rightBottom(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx + 2, ty - 1, kx, ky);
    }

    private static int bottomRight(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx + 1, ty - 2, kx, ky);
    }

    private static int topLeft(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx - 1, ty + 2, kx, ky);
    }

    private static int bottomLeft(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx - 1, ty - 2, kx, ky);
    }

    private static int leftTop(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx - 2, ty + 1, kx, ky);
    }

    private static int leftBottom(int count, int tx, int ty, int kx, int ky) {
        return count + recurse(count + 1, tx - 2, ty - 1, kx, ky);
    }

    private static boolean isSolved(int tx, int ty, int kx, int ky) {
        boolean solved = false;
        if ((tx == kx) && (ty == ky)) {
            solved = true;
        } else if ((tx + 2 == kx) && (ty + 1 == ky)) { // right top
            solved = true;
        } else if ((tx + 2 == kx) && (ty - 1 == ky)) { // right bottom
            solved = true;
        } else if ((ty + 2 == ky) && (tx + 1 == kx)) {// top right
            solved = true;
        } else if ((ty + 2 == ky) && (tx - 1 == kx)) {// top left
            solved = true;
        } else if ((tx - 2 == kx) && (ty + 1 == ky)) { // left top
            solved = true;
        } else if ((tx - 2 == kx) && (ty - 1 == ky)) {// left bottom
            solved = true;
        } else if ((ty - 2 == ky) && (tx + 1 == kx)) { // bottom right
            solved = true;
        } else if ((ty - 2 == ky) && (tx - 1 == kx)) { // bottom left
            solved = true;
        }

        return solved;
    }

}

4
সদৃশগুলি এড়ানোর জন্য এটি আরও অনুকূলিত করা যেতে পারে।
অরুণ

-1

এখানে মোস্তফা সর্দার Şanlı কোড ভিত্তিক একটি সি সংস্করণ রয়েছে যা একটি ফাইনিট বোর্ডের জন্য কাজ করে:

#include <stdio.h>
#include <math.h>

#define test(x1, y1, x2, y2) (sx == x1 && sy == y1 &&tx == x2 &&ty == y2) || (sx == x2 && sy == y2 && tx == x1 && ty==y1)

int distance(int sx, int sy, int tx, int ty) {
    int x, y, t;
    double delta;

    // special corner cases 
    if (test(1, 1, 2, 2) || 
        test(7, 7, 8, 8) || 
        test(7, 2, 8, 1) || 
        test(1, 8, 2, 7))
        return 4;

    // axes symmetry 
    x = abs(sx - tx);
    y = abs(sy - ty);

    // diagonal symmetry 
    if (x < y) {
        t = x;
        x = y;
        y = t;
    }

    // 2 corner cases
    if (x == 1 && y == 0)
        return 3;
    if (x == 2 && y == 2)
        return 4;

    // main
    delta = x - y;
    if (y > delta) {
        return (int)(delta - 2 * floor((delta - y) / 3));
    }
    else {
        return (int)(delta - 2 * floor((delta - y) / 4));
    }
}

পুনরাবৃত্তির সমাধানের বিরুদ্ধে প্রমাণ সহ এটি এখানে পরীক্ষা করুন


4
সীমাবদ্ধ সংখ্যক মামলা পরীক্ষা করা কোনও প্রমাণ নয়।
ব্লেন্ডারবেন্ডার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.