KNight MOVe shortest [closed] - algorithm

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
MY code is here: Question is to find min number of moves to go from one sq. to other in 8*8 chess board .
#include<iostream>
using namespace std;
int n;
int a[12][12];
int min1=1000,xd=5,yd=2,ys,xs,xsi,ysi;
int find_path(int xs,int ys)
{
cout<<xs<<" "<<ys<<endl;
if((xs==xd) && (ys==yd)) { cout<<"destiny schieved "<<endl; return 0;}
if(a[xs][ys]==1 || xs<0 || ys<0 || xs>7 || ys>7) return 10000;
a[xs][ys]=1;
int a1=1+(find_path(xs-2,ys+1)) ;
int b=1+(find_path(xs-2,ys-1)) ;
int c=1+(find_path(xs-1,ys+2)) ;
int d=1+(find_path(xs-1,ys-2)) ;
int d=1+(find_path(xs+2,ys+1)) ;
int e=1+(find_path(xs+2,ys-1)) ;
int f=1+(find_path(xs+1,ys+2)) ;
int g=1+(find_path(xs+1,ys-2)) ;
a[xs][ys]=0;
return min(a1,b,c,d,e,f,g);
}
int main()
{
int i,j,k;
for(i=0;i<8;i++)
for(j=0;j<8;j++)
a[i][j]=0;
cout<<"start"<<endl;
cout<<find_path(0,7);
system("pause");
return 0;
}
This is my code for traversing from one square to other in 8*8 chess board .
MY code gives wrong answer for some cases :
a[xs][ys]=1; is for preventing loops.
for eg answer for (0,7) ->>>> (5,2) is 4 but my algo gives 38 . MY coordinate axis are X: from left to right and Y-axis: from top to bottom . Please help me solving my problem.
Few solutions are:
(7,0) ->>> (0,7) : 6
(0,7) ->>> (5,2) :4
I have also tried another code which i later edited to get the above code:
int find_path(int xs,int ys,int path)
{
cout<<xs<<" "<<ys<<endl;
if((xs==xd) && (ys==yd)) { if(min1>path) min1=path; cout<<"destiny schieved "<<path<<endl; return 1;}
if(a[xs][ys]==1 || xs<0 || ys<0 || xs>7 || ys>7) return 0;
a[xs][ys]=1;
if(find_path(xs-2,ys+1,path+1)) {if(path==0) {cout<<"i am on start1"<<endl;} else return 1;}
if(find_path(xs-2,ys-1,path+1)) {if(path==0) {cout<<"i am on start2"<<endl;} else return 1; }
if(find_path(xs-1,ys+2,path+1)) {if(path==0) {cout<<"i am on start3"<<endl;} else return 1; }
if(find_path(xs-1,ys-2,path+1)) {if(path==0) {cout<<"i am on start4"<<endl;} else return 1;}
if(find_path(xs+2,ys+1,path+1)) {if(path==0) {cout<<"i am on start5"<<endl;} else return 1;}
if(find_path(xs+2,ys-1,path+1)) {if(path==0) {cout<<"i am on start6"<<endl;} else return 1;}
if(find_path(xs+1,ys+2,path+1)) {if(path==0) {cout<<"i am on start7"<<endl;} else return 1; }
if(find_path(xs+1,ys-2,path+1)) {if(path==0) {cout<<"i am on start8"<<endl;} else return 1; }
a[xs][ys]=0;
return 0;
}

It's often rewarding to think in terms of data structures instead of thinking in terms of algorithms.
In this case, the valid moves for a knight on a board constitute an undirected graph G where vertices denote board positions and edges denote valid moves. Hence, you might have nodes a1 and b3 connected by an edge, since a knight may move from a1 to b3 and vice versa.
Given that representation of the problem, it's fairly easy to compute the min number of moves for a knight to go from A to B, since it's the length of the shortest path from node A to node B in G.
to compute the shortest path for a given start node and all end nodes, use the Bellman-Ford algorithm with time complexity O(|V||E|).
to compute the shortest path for all pairs of nodes, use the Floyd-Warshall algorithm with time complexity O(|V|^3).

Related

As I read Djiktra's algo fails for negative edges but I implemented the same concept and my code is working? Is there some bug?

The code works for negative edges too and I have used priority queue
please check it and let me know what's wrong with it and why is this working even for negative edges.
Constraint: edges should be less than 10000 length
Am I doing something wrong here?
As I read Djiktra's algo fails for negative edges but I implemented the same concept and my code is working? Is there some bug?
#include<iostream>
#include<queue>
using namespace std;
struct reach
{
int n;
int weight;
};
struct cmp
{
bool operator()(reach a, reach b)
{
return a.weight>b.weight;
}
};
class sp
{
int *dist;
int n;
int **graph;
int src;
public:
sp(int y)
{
n=y;
src=1;
dist=new int[n+1];
graph=new int*[n+1];
for(int i=0;i<=n;i++)
{
graph[i]=new int[n+1];
}
for(int i=2;i<=n;i++)
{
dist[i]=10000;
}
// cout<<INT_MAX<<endl;
dist[src]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
graph[i][j]=10000;
}
}
graph[1][1]=0;
}
void read()
{
int a;
cout<<"enter number of edges"<<endl;
cin>>a;
cout<<"now enter the two vertices which has an edge followed by the weight of the edge"<<endl;
while(a--)
{//cout<<"location: "<<i<<" : "<<j<<endl;
int as, ad,val;
cin>>as>>ad>>val;
graph[as][ad]=val;
}
}
void finder()
{cout<<"enetered"<<endl;
priority_queue<reach, vector<reach>, cmp> q;
for(int i=1;i<=n;i++)
{
if(dist[src]+graph[src][i]<dist[i])
{
reach temp;
temp.n=i;
cout<<i<<endl;
temp.weight=graph[src][i];
q.push(temp);
dist[i]=graph[src][i]+dist[src];
}
}
while(q.empty()!=1)
{
reach now =q.top();
//cout<<" we have here: "<<now.n<<endl;
q.pop();
for(int i=1;i<=n;i++)
{
if((dist[now.n] + graph[now.n][i])<dist[i])
{
dist[i]=dist[now.n]+graph[now.n][i];
cout<<"it is: "<<i<<" : "<<dist[i]<<endl;
reach temp;
temp.n=i;
//cout<<temp.n<<endl;
temp.weight=graph[now.n][i];
q.push(temp);
}
}
}
}
void print()
{
for(int i=1;i<=n;i++)
{
cout<<"we have: "<<dist[i]<<" at "<<i;
cout<<endl;
}
cout<<endl;
}
};
int main()
{cout<<"enter no. of vertices"<<endl;
int n;
cin>>n;
sp sp(n);
sp.read();
sp.finder();
sp.print();
}
Consider this example:
Undirected Graph(6v,8e)
Edges (v1-v2 (weight)):
1-2 (2)
2-3 (1)
1-3 (-2)
1-6 (-2)
3-6 (-3)
5-6 (1)
4-5 (2)
2-5 (1)
Now, Let source be 1 and destination be 4. There is one cycle from source to source (1-3-6-1) which weighs (-7). So, lets list a few paths from source to destination with weights:
1-6-5-4 (1)
1-3-6-5-4 (-2)
1-3-6-1-3-6-5-4 (-9)
1-3-6-1-3-6-1-3-6-5-4 (-16)
etc.
So, which path is the shortest? Since it is ambiguous, the algorithm does not work. Now, you can argue that if a node is visited, you will not update it. In this case, you will not get the correct answer. May be there are some cases where in-spite of having negative edges, algo gives correct results, but this is not how Dijkstra works.
A really simple way to understand Dijkstra is that it performs BFS on the graph, from source till destination, and in every step it updates the visited nodes. So, if there is a node n which has cost c and a few levels deep in bfs, its cost becomes k (<c). Then again you will have to update all the nodes visited from n for their shorter paths (because path to n is now shorter). Since graph has negative edges, if it has a cycle, n will keep updating infinitely and will never end.
The simplest graph for which Dijkstra's algorithm fails with negative weights has adjacency matrix
0 1 2
1 0 -3
2 -3 0
and looks for a route from vertex 0 to vertex 1. The first vertex to come off the priority queue is vertex 1 at distance 1, so that's the route returned. But there was a route of total weight -1 via a vertex which is still in the priority queue, with weight 2.

Optimal solution for the "celebrity" algorithm

Among n persons,a "celebrity" is defined as someone
who is known by everyone but does not know anyone. The
problem is to identify the celebrity, if one exists, by asking the
question only of the form, "Excuse me, do you know the person
over there?" (The assumption is that all the answers are correct,
and even that celebrity will also answer.)
The goal is to minimize the number of questions.
Is there a solution of the order less than the obvious O(n^2) here?
Using the analysis of the celebrity problem here
Brute-force solution. The graph has at most n(n-1) edges, and we can compute it by asking a question for each potential edge. At this
point, we can check whether a vertex is a sink by computing its
indegree and its outdegree. This brute-force solution asks n(n-1)
questions. Next we show how to to do this with at most 3(n-1)
questions and linear place.
An elegant solution. Our algorithm consists of two phases: in the elimination phase, we eliminate all but one person from being the
celebrity; in the verification phase we check whether this one
remaining person is indeed a celebrity. The elimination phase
maintains a list of possible celebrities. Initially it contains all n
people. In each iteration, we delete one person from the list. We
exploit the following key observation: if person 1 knows person 2,
then person 1 is not a celebrity; if person 1 does not know person 2,
then person 2 is not a celebrity. Thus, by asking person 1 if he knows
person 2, we can eliminate either person 1 or person 2 from the list
of possible celebrities. We can use this idea repeatedly to eliminate
all people but one, say person p. We now verify by brute force
whether p is a celebrity: for every other person i , we ask person p
whether he knows person i , and we ask persons i whether they know
person p . If person p always answers no, and the other people always
answer yes, the we declare person p as the celebrity. Otherwise, we
conclude there is no celebrity in this group.
Divide all the people in pairs.
For every pair (A, B), ask A if he knows B.
if the answer is yes, A can not be the celebrity, discard him.
if the answer is no, B can not be the celebrity, discard him.
Now, only half the people remains.
Repeat from 1 until just one person remains.
Cost O(N).
Here is O(N) time algorithm
Push all the elements into stack.
Remove top two elements(say A and B), and keep A if B knows A and A does not know B.
Remove both A,B is both know each other or both does not know each other
This question can be solved using graphs (indegree and outdegree concept) in O(N^2) Time complexity.
We can also solve this question in O(N) time and O(1) space using a simple two-pointer concept.
We are going to compare two persons at a time one from beginning and other from the end and we will remove that person from consideration which cannot be a celebrity. For example, if there are two persons X and Y and X can identify person Y then surely X cannot be a celebrity as it knows a person inside this party. Another case would be when X does not know Y and in this case, Y cannot be a celebrity as there is at least one person who does not know him/her inside a party. Using this intuition two-pointer concept can be applied to find the celebrity inside this party.
I found a good explanatory video on Youtube by algods.
You can refer to this video for a better explanation.
Video Link:
https://youtu.be/aENYremq77I
Here is my solution.
#include<iostream>
using namespace std;
int main(){
int n;
//number of celebrities
cin>>n;
int a[n][n];
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
cin>>a[i][j];
}
}
int count = 0;
for(int i = 0;i < n;i++){
int pos = 0;
for(int j = 0;j < n;j++){
if(a[i][j] == 0){
count = count + 1;
}
else{
count = 0;
break;
}
}
if(count == n){
pos = i;
cout<<pos;
break;
}
}
return 0;
}
This is how I did it :)
Question - A celebrity is defined someone whom everyone else knows of, but do not know anyone. Given N people (indexed 0...(N-1)), and a function knowsOf defined
as follows: knowsOf(int person0, int person1) = true if person 0 knows person 1, and false otherwise
Find out the celebrity in the N given people if there is any.
// return -1 if there is no celeb otherwise return person index/number.
public int celeb(int n) {
int probaleCeleb = 0;
for(int i =1 ; i < n; i++) {
if(knowsOf(probaleCeleb , i)) { // true /false
probaleCeleb = i;
}
}
for(int i =0 ; i < n; i++) {
if( i != probaleCeleb &&
(!knowsOf( i , probaleCeleb) || (knowsOf( probaleCeleb , i)) ) {
probaleCeleb = -1;
break;
}
}
return probaleCeleb;
}
}
public class Solution {
public int findCelebrity(int n) {
if (n <= 1) {
return -1;
}
int left = 0;
int right = n - 1;
// First find the right candidate known by everyone, but doesn't know anyone.
while (left < right) {
if (knows(left, right)) {
left++;
} else {
right--;
}
}
// Validate if the candidate knows none and everyone knows him.
int candidate = right;
for (int i = 0; i < n; i++) {
if (i != candidate && (!knows(i, candidate) || knows(candidate, i))) {
return -1;
}
}
return candidate;
}
}
int findCelebrity(int n) {
int i=0;
for(int j=1;j<n;j++){
if(knows(i,j)){
i=j;
}
}
for(int j=0;j<n;j++){
if(j!=i && (knows(i,j)|| !knows(j,i))){
return -1;
}
}
return i;
}

Algorithm to find other two sides of a trianlge when one side is given [duplicate]

This question already has answers here:
Algorithm to determine whether a given number N can become hypotenuse of right triangle with all 3 integral sides
(5 answers)
Closed 9 years ago.
There is a triangle, and its hypotenuse length is given to us. Now our task is to find whether other two sides are also integer or not.
For above question, I build one code, but that is inefficient, can you suggest any efficient algorithm for the same.
My work
#include<stdio.h>
#include<cmath>
using namespace std;
int isInt(double x) {
if( (x - (int)x) == 0 ) return 1;
return 0;
}
main() {
int S;
int flag = 0;
scanf("%d", &S);
flag = 0;
for(int i = 1; i < S; i++) {
if( isInt(sqrt(S*S - i*i)) ) {
printf("EXIST\n");
flag = 1;
break;
}
}
if(!flag) printf("NOT EXIST\n");
return 0;
}
If I understand you correctly, you are trying to answer the question "Does an integer sized right triangle with hypothenuse S exist?".
Immediate improvements to your method:
Loop i from 1 to S/2 instead of 1 to S-1.
Actually, S/2 itself is not necessary either, since that would imply a==b, and c must therefore contain an odd number of sqrt(2)-factors.
(No need to set flag=0 twice.)
Instead of checking for integer square roots (sqrt operation is time consuming), you could use this alternative integer-only variant:
int check(int c){
int a=1;
int b=c-1;
int cc=c*c;
while(a<b){
int sum=a*a+b*b;
if(sum==cc) return true;
if(sum<cc){
a++;
}else{
b--;
}
}
return false;
}
(code not tested.)
There are other ways to answer the question involving theorems for expressibility as the sum of two squares applied to the square of the given hypothenuse. However, these generally involve factorization, which is also a hard problem.
(edit: removed wrong statement regarding factorization complexity)
Further info:
http://en.wikipedia.org/wiki/Pythagorean_triple
http://en.wikipedia.org/wiki/Fermat's_theorem_on_sums_of_two_squares
(see comments, I'm not allowed to post enough links)

How to find which vertices are in a graph cycle

eg. for 1->2, 2->3, 3->4, 4->2, I want to print 2, 3, 4.
I tried DFS, and when I found vertex I visited before, I go to parent until I don't get this vertex, but it does not work well. Sometimes it enters an infinite loop.
Run dfs:
int i;
for (i = 0; i < MAX_VER; i += 1)
if (ver[i].v == 0 && ver[i].nb > 0)
dfs(i);
dfs:
ver[v].v = 1;
int i;
for (i = 0; i < ver[v].nb; i += 1) {
ver[ver[v].to[i]].p = v;
if (ver[ver[v].to[i]].v == 0)
dfs(ver[v].to[i]);
else
// cycle found
printCycle(ver[v].to[i]);
}
and print cycle:
printf("\cycle: %d ", v);
int p = ver[v].p;
while (p != v) {
printf("%d(%d) ", p, v);
p = ver[p].p;
}
printf("\n");
Vertex struct:
int *to; // neighbor list
int nb; // how many neighbor
int p; // parent
short v; // was visited? 0 = false, 1 = true
It sounds like you are looking for "Strongly Connected Components" - so you are in luck, there is a well known algorithm for finding these in a graph. See Tarjan.
The algorithm is pretty well described in that article, but it's a bit long winded so I won't paste it here. Also, unless you are doing this for study you will probably be better off using an existing implementation, it's not that hard to implement but it's not that easy either.
EDIT. It looks like this question is actually a dupe... it pains me to say this but it probably needs to be closed, sorry. See Best algorithm for detecting cycles in a directed graph
You should use vertex coloring to avoid infinite loop in DFS.
At first all vertices are marked as WHITE. When you discover a vertex at first time (it is marked as WHITE) you should mark it is as GREY. If you discovered a GREY vertex you would find a loop.

find minimum step to make a number from a pair of number

Let's assume that we have a pair of numbers (a, b). We can get a new pair (a + b, b) or (a, a + b) from the given pair in a single step.
Let the initial pair of numbers be (1,1). Our task is to find number k, that is, the least number of steps needed to transform (1,1) into the pair where at least one number equals n.
I solved it by finding all the possible pairs and then return min steps in which the given number is formed, but it taking quite long time to compute.I guess this must be somehow related with finding gcd.can some one please help or provide me some link for the concept.
Here is the program that solved the issue but it is not cleat to me...
#include <iostream>
using namespace std;
#define INF 1000000000
int n,r=INF;
int f(int a,int b){
if(b<=0)return INF;
if(a>1&&b==1)return a-1;
return f(b,a-a/b*b)+a/b;
}
int main(){
cin>>n;
for(int i=1;i<=n/2;i++){
r=min(r,f(n,i));
}
cout<<(n==1?0:r)<<endl;
}
My approach to such problems(one I got from projecteuler.net) is to calculate the first few terms of the sequence and then search in oeis for a sequence with the same terms. This can result in a solutions order of magnitude faster. In your case the sequence is probably: http://oeis.org/A178031 but unfortunately it has no easy to use formula.
:
As the constraint for n is relatively small you can do a dp on the minimum number of steps required to get to the pair (a,b) from (1,1). You take a two dimensional array that stores the answer for a given pair and then you do a recursion with memoization:
int mem[5001][5001];
int solve(int a, int b) {
if (a == 0) {
return mem[a][b] = b + 1;
}
if (mem[a][b] != -1) {
return mem[a][b];
}
if (a == 1 && b == 1) {
return mem[a][b] = 0;
}
int res;
if (a > b) {
swap(a,b);
}
if (mem[a][b%a] == -1) { // not yet calculated
res = solve(a, b%a);
} else { // already calculated
res = mem[a][b%a];
}
res += b/a;
return mem[a][b] = res;
}
int main() {
memset(mem, -1, sizeof(mem));
int n;
cin >> n;
int best = -1;
for (int i = 1; i <= n; ++i) {
int temp = solve(n, i);
if (best == -1 || temp < best) {
best = temp;
}
}
cout << best << endl;
}
In fact in this case there is not much difference between dp and BFS, but this is the general approach to such problems. Hope this helps.
EDIT: return a big enough value in the dp if a is zero
You can use the breadth first search algorithm to do this. At each step you generate all possible NEXT steps that you havent seen before. If the set of next steps contains the result you're done if not repeat. The number of times you repeat this is the minimum number of transformations.
First of all, the maximum number you can get after k-3 steps is kth fibinocci number. Let t be the magic ratio.
Now, for n start with (n, upper(n/t) ).
If x>y:
NumSteps(x,y) = NumSteps(x-y,y)+1
Else:
NumSteps(x,y) = NumSteps(x,y-x)+1
Iteratively calculate NumSteps(n, upper(n/t) )
PS: Using upper(n/t) might not always provide the optimal solution. You can do some local search around this value for the optimal results. To ensure optimality you can try ALL the values from 0 to n-1, in which worst case complexity is O(n^2). But, if the optimal value results from a value close to upper(n/t), the solution is O(nlogn)

Resources