[Noip2017普及组]棋盘
写起来有点烦...
#include<bits/stdc++.h> using namespace std; const int N=105; const int inf=0x3f3f3f3f; int dir[4][2]={{-1,0},{0,-1},{0,1},{1,0}};//四个方向定义 int s[N][N],p[N][N],n,m,flag=0,ans=inf; void dfs(int x,int y,int cnt,int k) { if(cnt>=p[x][y]) return; //如果花费已经大于最小值,则停止搜索 p[x][y]=cnt; //否则更新该点最小值 if(x==n&&y==n)//判断是否到达终点 { flag=1; //标记为可以到达终点,为主函数判断作铺垫 ans=min(ans,cnt);//更新答案 return; } for(int i=0;i<4;i++)//枚举四个方向 { int tx=x+dir[i][0];//求出往当前方向走的坐标 int ty=y+dir[i][1]; if(tx<1||tx>n||ty<1||ty>n) continue;//判断是否越界 if(s[tx][ty]!=0)//该点有颜色 { if(s[x][y]==s[tx][ty]) dfs(tx,ty,cnt,0); //如果该点的颜色与上一个经过的点颜色一样则不需要花费魔法 else dfs(tx,ty,cnt+1,0);//若颜色不一样,则花费+1 } else { if(k==0)//若上一次没有使用魔法 { s[tx][ty]=s[x][y]; //改变颜色 dfs(tx,ty,cnt+2,1); //花费+2,标记使用了魔法 s[tx][ty]=0; //回溯 } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)p[i][j]=inf; //先赋值为一个极大值 for(int i=0;i<m;i++) { int x,y,c; scanf("%d%d%d",&x,&y,&c); if(c==0)s[x][y]=2; //格子为红色 else s[x][y]=c;//格子为黄色 } dfs(1,1,0,0);//深搜 if(flag) printf("%d\n",ans); else printf("-1\n"); return 0; }
#include<bits/stdc++.h> using namespace std; #define inf 0x4f4f4f4f int f[1001][1001]; int mp[1001][1001]; int ans=inf; int dx[4]= {-1,0,1,0}; int dy[4]= {0,-1,0,1}; int m,n; inline void DFS(int x,int y,int tot,bool flag) { if(x < 1 || y < 1 || x > n || y > n) return; if(!f[x][y]) //如果当前点是无色的,则无效的 return; if(tot>= mp[x][y]) //如果用的费用大于当前点的 return; mp[x][y] = tot; if(x == n && y == n) { if(tot < ans) ans = tot; return; } for(register int i=0; i<=3; ++i) { int xx=x+dx[i]; int yy=y+dy[i]; if(f[xx][yy]) //如果是有color的 { if(f[xx][yy]==f[x][y]) //如果相同的color的 DFS(xx,yy,tot,false); else DFS(xx,yy,tot+1,false); } else if(!f[xx][yy]&&!flag) //如果走到的格子是无color的,且可以使用改色技能 { f[xx][yy]=f[x][y]; DFS(xx,yy,tot+2,true); f[xx][yy]=0; } } } int main() { scanf("%d%d",&n,&m); memset(mp,inf,sizeof(mp)); for(register int i=1; i<=m; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); f[x][y]=z+1; } DFS(1,1,0,false); if(ans==inf)printf("-1\n"); else printf("%d\n",ans); return 0; }
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int m,n;
int mp[110][110],f[110][110];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
void dfs(int x,int y,int z)
{
for(int i=0;i<4;i++)
{
int tx=x+dx[i];
int ty=y+dy[i];
if(tx<1||ty<1||tx>m||ty>m)
continue;
int r=-1;
if(mp[x][y]==mp[tx][ty]&&mp[tx][ty])
//如果是有color的,且同色的
r=0;
else
{
if(mp[tx][ty])
//如果目标点是有色的
r=1;
if(!mp[tx][ty]&&z)
//如果目标点是无色的,且可以采用改色的技能时
r=2;
}
if(r!=-1&&(f[x][y]+r<f[tx][ty]||!f[tx][ty]))
//如果可以移动的话,且移到目标的代价更优,或者目标点从前没走过
{
f[tx][ty]=f[x][y]+r;
if(r==2)
//如果使用了改色的技能的话
{
mp[tx][ty]=mp[x][y];
dfs(tx,ty,0);
//走到(tx,ty)且改色技能失效
mp[tx][ty]=0;
}
else
dfs(tx,ty,1);
}
}
}
int main()
{
f[1][1]=1;
scanf("%d%d",&m,&n);
int x,y,c;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&c);
mp[x][y]=c+1;
//题面居然会0代表红色,于是给所有color加1
}
dfs(1,1,1);
printf("%d",f[m][m]-1);
return 0;
}