题目描述
【背景】
据说在意大利的米兰市的地下,埋藏着一堆的宝藏。一天,一个名叫 Shevchenko 的人来到这地下宝库,准备把所有的宝藏都搬回家。当他来到这里时,发现这里是一个迷宫,宝藏埋藏在各个角落,在另一端有个出口,当他每捡到一个宝藏将恢复一定的体力值。
【任务】
由于 Sheva(Shevchenko 的昵称)的体力有限,他必须合理的安排体力,才能既捡完所有的宝藏又能离开这个宝库,现在请你编一程序,帮 Sheva 解决这个问题。在迷宫中每走一格,Sheva 的体力值都会减少一定的数量,如果体力值小等于 0,他将不能再前行。
输入输出格式
输入格式:
第一行输入 Sheva 刚开始的体力值和每走一格消耗的体力值(均为整数)。
第二行输入宝藏的个数 N(N<=10)。
第三行到第 N+2 行每行有3 个数,前两个数为宝藏的坐标 X、Y,第 3 个数为捡到这宝藏将获得的体力值。
下一行输入迷宫的行数 A和列数 B。(A、B<=50)
以下 A行将输入迷宫的地形。0 表示不能走,1 表示可以走(宝藏所在的位置也为 1)。
最后一行输入出口的坐标(起点坐标为(1,1))。
输出格式:
如果 Sheva 能走出迷宫,将只输出一个数,为他所剩的体力值。否则,将输出“no,he cannot”(注意大小写)。
输入输出样例
输入样例#1:
100 1
4
1 4 2
2 4 2
4 4 2
5 3 2
5 5
1 1 0 1 0
0 1 1 1 0
0 1 0 0 1
0 1 1 1 0
0 1 1 1 1
5 5
输出样例#1:
92
正文
SCOI-14的其他题目都与数论有或多或少的关系,该题目应当是其中较为简单的一道。
题目简意
在图中(1表示可走,0表示不可走)有N个坐标,走到坐标i可增加Ai体力值,另外,每走一步消耗tl体力值,求到终点时最多还剩多少体力值。
算法分析
看数据范围:
(N<=10)(A、B<=50)
数据量极小,边权为1,可采用bfs预处理出起点,终点及宝藏之间的最短路径。
时间复杂度:O (N*A*B)
求得后,暴力枚举所有可能的路径,以dfs实现。
时间复杂度:O(N!)
极限数据(N=10,A=B=50)下,算法时间复杂度为O(10!+10*50*50)O(4000000)
#include<bits/stdc++.h>
using namespace std;
int TL,tl,N,n,m,d[20][20],br[60][60],maxn=-0x7fffff,had[20];
bool _map[60][60];
bool vis[60][60];
int dx[5]={0,-1,1,0,0};
int dy[5]={0,0,0,-1,1};
struct B{
int x;
int y;
int add_tl;
}ed,bz[13];
struct S{
int x;
int y;
int step;
};
queue<S> q;
void dfs(int s,int val,int k)
{
if(k==N)
{
maxn=max(maxn,val-d[s][N+1]);
return;
}
for(int i=1;i<=N;i++)
{
if(!had[i])
{
had[i]=1;
dfs(i,val-d[s][i]+bz[i].add_tl,k+1);
had[i]=0;
}
}
return;
}
int main()
{
cin>>TL>>tl;
cin>>N;
memset(br,-1,sizeof(br));
memset(d,0x3f,sizeof(d));
for(int i=1;i<=N;i++)
{
cin>>bz[i].x>>bz[i].y>>bz[i].add_tl;
br[bz[i].x][bz[i].y]=i;
}
bz[0].x=bz[0].y=1;
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>_map[i][j];
cin>>ed.x>>ed.y;
bz[N+1].x=ed.x;
bz[N+1].y=ed.y;
br[1][1]=0;
br[ed.x][ed.y]=N+1;
for(int i=0;i<=N+1;i++)
{
q.push((S){bz[i].x,bz[i].y,0});
memset(vis,0,sizeof(vis));
vis[bz[i].x][bz[i].y]=1;
// cout<<i<<":\n";
while(!q.empty())
{
S tmp=q.front();
q.pop();
int ux=tmp.x,uy=tmp.y,us=tmp.step;
// cout<<ux<<' '<<uy<<' '<<us<<endl;
for(int j=1;j<=4;j++)
{
int xx=ux+dx[j];
int yy=uy+dy[j];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&_map[xx][yy]&&!vis[xx][yy])
{
if(br[xx][yy]!=-1)
{
d[i][br[xx][yy]]=d[br[xx][yy]][i]=(us+1)*tl;
// printf("add_edge(%d,%d,%d)\n",i,br[xx][yy],(us+1)*tl);
}
q.push((S){xx,yy,us+1});
vis[xx][yy]=1;
}
}
}
}
br[1][1]=br[ed.x][ed.y]=-1;
dfs(0,TL,0);
for(int i=0;i<=N+1;i++)
{
for(int j=0;j<=N+1;j++)
{
if(i!=j&&d[i][j]==d[19][19])
{
cout<<"no,he cannot";
return 0;
}
}
}
if(maxn>=0) cout<<maxn;
else cout<<"no,he cannot";
return 0;
}