华师一附中OI组
标题:
P3956 棋盘
[打印本页]
作者:
倚窗倾听风吹雨
时间:
2018-8-24 16:13
标题:
P3956 棋盘
https://www.luogu.org/problemnew/show/P3956
题目描述
有一个 m×m 的棋盘,棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。
任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的), 你只能向上、 下、左、 右四个方向前进。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费 1 个金币。
另外, 你可以花费 2 个金币施展魔法让下一个无色格子暂时变为你指定的颜色。但这个魔法不能连续使用, 而且这个魔法的持续时间很短,也就是说,如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法; 只有当你离开这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而当你离开了这个位置(施展魔法使得变为有颜色的格子)时,这个格子恢复为无色。
现在你要从棋盘的最左上角,走到棋盘的最右下角,求花费的最少金币是多少?
输入输出格式
输入格式:
第一行包含两个正整数 m, n,以一个空格分开,分别代表棋盘的大小,棋盘上有颜色的格子的数量。
接下来的 n 行,每行三个正整数 x, y, c , 分别表示坐标为 (x,y)的格子有颜色 c 。
其中 c=1 代表黄色, c=0 代表红色。 相邻两个数之间用一个空格隔开。 棋盘左上角的坐标为 (1, 1) ,右下角的坐标为 (m,m) 。
棋盘上其余的格子都是无色。保证棋盘的左上角,也就是 (1, 1) 一定是有颜色的。
输出格式:
一个整数,表示花费的金币的最小值,如果无法到达,输出 −1 。
输入输出样例
输入样例#1:
5 7
1 1 0
1 2 0
2 2 1
3 3 1
3 4 0
4 4 1
5 5 0
输出样例#1:
8
输入样例#2:
5 5
1 1 0
1 2 0
2 2 1
3 3 1
5 5 0
输出样例#2:
-1
作者:
倚窗倾听风吹雨
时间:
2018-8-24 16:14
之前直接BFS只过了一个点。其他全部TLE......于是用了记忆化bfs搜索+减枝
#include<iostream>
#include<queue>
using namespace std;
int ans=999999,m,n,a1,a2,pi,dr[4]={-1,0,+1,0},dc[4]={0,+1,0,-1};
int a[101][101],f[101][101];
bool flag=0;
struct node
{
int r,c,col;
int cost;
}p;
queue<node>q;
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
cin>>a1>>a2;
cin>>pi;
a[a1][a2]=pi+1;
}
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
f[i][j]=99999;
p.r=1;p.c=1;
p.cost=0;
p.col=a[1][1];
f[1][1]=0;
q.push(p);
while(!q.empty())
{
if(q.front().r==m && q.front().c==m)
{
ans=min(ans,q.front().cost);
flag=1;
q.pop();
continue;
}
if(q.front().cost>ans)
{
q.pop();
continue;
}
for(int i=0;i<=3;i++)
if(q.front().r+dr[i]>=1 && q.front().c+dc[i]>=1 && q.front().r+dr[i]<=m && q.front().c+dc[i]<=m)
{
p.r=q.front().r+dr[i];
p.c=q.front().c+dc[i];
p.col=a[p.r][p.c];
if(p.col==0 && a[q.front().r][q.front().c]==0)continue;
if(p.col==q.front().col)
p.cost=q.front().cost;
else
{
if(a[p.r][p.c]!=0)
p.cost=q.front().cost+1;
else
{
p.cost=q.front().cost+2;
p.col=q.front().col;
}
}
if(p.cost<f[p.r][p.c])
{
f[p.r][p.c]=p.cost;
q.push(p);
}
}
q.pop();
}
if(flag==1)cout<<f[m][m]<<endl;
else cout<<"-1"<<endl;
return 0;
}
复制代码
作者:
黄煦喆
时间:
2018-8-30 17:04
本帖最后由 黄煦喆 于 2019-7-5 09:54 编辑
#include<iostream>
#include<cstring>
using namespace std;
int m,n,sum,a[101][101],s[101][101];
bool b[101][101];
int dx[4]= {0,0,+1,-1};
int dy[4]= {+1,-1,0,0};
void dfs(int x,int y,bool magic)
{
if(sum>=s[x][y])return;
else s[x][y]=sum;
if(x==m&&y==m)return;
else for(int i=0; i<4; i++)
{
int tx=x+dx[i];
int ty=y+dy[i];
if(!b[tx][ty]&&tx>=1&&tx<=m&&ty>=1&&ty<=m)
{
if(a[tx][ty]==a[x][y])
{
b[tx][ty]=1;
dfs(tx,ty,1);
b[tx][ty]=0;
}
else if(a[tx][ty]!=a[x][y]&&a[tx][ty]!=-1)
{
b[tx][ty]=1,sum++;
dfs(tx,ty,1);
sum--,b[tx][ty]=0;
}
else if(a[tx][ty]==-1&&magic)
{
b[tx][ty]=1, a[tx][ty]=a[x][y];
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2