Description
New game是在一个M*M的特殊棋盘(棋盘的第i行都标上了数字i)上进行的新式游戏。给定一个数字N,要求选手把一个棋子从左上角(1,1)移到右下角(M,M),移动时只能往右或往下。要求移动后经过的数字和为N,且拐弯的次数最少。
如果对给出的N,选手不能找出移动方案使得经过的数字和为N或找出的路径拐弯次数不是最少,选手就输了。所以,选手一定千方百计要找出满足条件的路径!!
Input
两个正整数M,N(其中M<=16),数据保证有解。
Output
最少拐弯数。
Sample
Input
4 22
Output
1
答案:
#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
const int N = 35;
using namespace std;
int m,n;
bool vis[N][N];
int mp[N][N];
int dir[2][2]= {{1,0},{0,1}};
int minn;
void DFS(int x,int y,bool flag,int id,int cnt)
{
if(id>minn) //最优剪
return ;
if(cnt>n) //可行剪
return ;
if(x==m&&y==m)
{
if(cnt==n)
minn=min(minn,id);
return ;
}
int i;
for(i=0; i<2; i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx>=1&&xx<=m&&yy>=1&&yy<=m&&!vis[xx][yy])
{
vis[xx][yy]=1;
if(cnt==1)
{
DFS(xx,yy,i,id,cnt+mp[xx][yy]);
}
else
{
if(i!=flag)
DFS(xx,yy,i,id+1,cnt+mp[xx][yy]);
else
DFS(xx,yy,i,id,cnt+mp[xx][yy]);
}
vis[xx][yy]=0;
}
}
}
void init()
{
int i,j;
for(i=1; i<=m; i++)
for(j=1; j<=m; j++)
mp[i][j]=i;
}
int main ()
{
while(cin>>m>>n)
{
memset(vis,0,sizeof(vis));
init();
vis[1][1]=1;
minn=INF;
DFS(1,1,0,0,1);
cout<<minn<<endl;
}
return 0;
}