/*
HDU 1044 Collect More Jewels
走迷宫,问在规定时间内从起点到终点最多可以收集到宝物的价值是多少。
先bfs找出所有宝物及起点和终点这些位置之间的最短距离,再起点dfs最大。
加个剪枝,如果已经拿到所有宝物了,就不再搜索。
AC G+ 31MS 560K
*/
/*
在一个迷宫中,从起点走到终点,还有几个宝物,问在给定的时间内,
到达终点后所能获取的最大价值。
思路:
先用bfs求出入口,宝物,出口,两两之间的最短距离。
在用dfs搜索所有情况,求出从入口走到出口能获得的最大价值。
熟悉两种搜索的优缺点:
BFS: 对于解决最短或最少问题特别有效,而且寻找深度小,
但缺点是内存耗费量大(需要开大量的数组单元用来存储状态)。
DFS:对于解决遍历和求所有问题有效,对于问题搜索深度小的时候处理速度迅速,
然而在深度很大的情况下效率不高
*/
#include<stdio.h>
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
int W,H,L,M;//区域是H行W列的,L是时间限制,M是宝石的数量
int val[60];//宝石的价值,1-M
char map[60][60];
bool used[60][60];//BFS时访问标记
bool vis[60];//dfs时访问标记
int step[60][60];
int ans;//结果
int sum;//所有的宝石的价值总和
int move[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
int dis[60][60];//记录初始位置、各宝石和出口两两间的距离
queue<int>q;
//从(x1,y1)点到其它点的距离,s(0-M+1)是该点编号,0表示初始位置
//M+1表示出口,1-M表示第i个宝物堆
void bfs(int x1,int y1,int s)
{
while(!q.empty())q.pop();
memset(used,false,sizeof(used));
memset(step,0,sizeof(step));
int u=x1*W+y1;
q.push(u);
used[x1][y1]=true;
step[x1][y1]=0;
while(!q.empty())
{
u=q.front();
q.pop();
int x=u/W;
int y=u%W;
for(int i=0;i<4;i++)
{
int xx=x+move[i][0];
int yy=y+move[i][1];
if(xx<0||xx>=H||yy<0||yy>=W)continue;
if(used[xx][yy]||map[xx][yy]=='*')continue;
used[xx][yy]=true;
step[xx][yy]=step[x][y]+1;
if(map[xx][yy]=='@')dis[s][0]=step[xx][yy];
else if(map[xx][yy]=='<') dis[s][M+1]=step[xx][yy];
else if(map[xx][yy]>='A'&&map[xx][yy]<='J')
dis[s][map[xx][yy]-'A'+1]=step[xx][yy];
q.push(xx*W+yy);
}
}
}
//dfs,s表示当前点,value表示获得的价值,time表示花费的时间
void dfs(int s,int value,int time)
{
if(time>L)return;//超出限制时间
if(ans==sum) return;//已经得到了最大的价值,剪枝(没有这个会超时)
if(s>M)
{
if(value>ans)ans=value;
return;
}
for(int i=0;i<=M+1;i++)
{
if(dis[s][i]==0||vis[i])continue;
vis[i]=true;
dfs(i,value+val[i],time+dis[s][i]);
vis[i]=false;
}
}
int main()
{
// freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
scanf("%d",&T);
int iCase=0;
while(T--)
{
memset(dis,0,sizeof(dis));
iCase++;
scanf("%d%d%d%d",&W,&H,&L,&M);
sum=0;
ans=-1;
for(int i=1;i<=M;i++)
{
scanf("%d",&val[i]);
sum+=val[i];
}
val[0]=val[M+1]=0;//这个很重要啊,WR到死啊
for(int i=0;i<H;i++)
scanf("%s",&map[i]);
for(int i=0;i<H;i++)
for(int j=0;j<W;j++)
{
if(map[i][j]=='@') bfs(i,j,0);
else if(map[i][j]=='<') bfs(i,j,M+1);
else if(map[i][j]>='A'&&map[i][j]<='J')
bfs(i,j,map[i][j]-'A'+1);
}
memset(vis,false,sizeof(vis));
vis[0]=true;
dfs(0,0,0);
printf("Case %d:\n",iCase);
if(ans>=0)printf("The best score is %d.\n",ans);
else printf("Impossible\n");
if(T>0)printf("\n");
}
return 0;
}
Rescue
#include<stdio.h>
#define max 32000
int n, m, time, visited[202][202], map[202][202], mx[5] = {0, 0, 0, -1, 1}, my[5] = {0, 1, -1, 0, 0}, ax, ay, ex, ey;
void init();
int dfs(int x, int y, int t);
int main()
{
init();
return 0;
}
void init()
{
int i, j;
char str[203];
while(scanf("%d %d\n", &n, &m) != EOF){
time = max;
for(i = 0; i <= n + 2; ++i)
for(j = 0; j <= m + 2; ++j){
map[i][j] = -1;
visited[i][j] = -1;
}
for(i = 1; i <= n; ++i){
gets(str);
for(j = 0; j <= m - 1; ++j)
if(str[j] == '.')
visited[i][j + 1] = 1;
else
if(str[j] == 'a'){
ax = i;
ay = j + 1;
}
else
if(str[j] == 'r'){
ex = i;
ey = j + 1;
visited[i][j + 1] = 1;
}
else
if(str[j] == 'x')
visited[i][j + 1] = 2;
}
dfs(ax, ay, 0);
if(time != max)
printf("%d\n", time);
else
printf("Poor ANGEL has to stay in the prison all his life.\n" );
}
}
int dfs(int x, int y, int t){
int i, ch, xn, yn;
if(x == ex && y == ey){
if(t < time)
time = t;
return 0;
}
else{
for(i = 1; i <= 4; ++i){
xn = x + mx[i];
yn = y + my[i];
if((visited[xn][yn] == 1 || visited[xn][yn] == 2) && t + visited[xn][yn] <= time){
if(map[xn][yn] == -1 || t + visited[xn][yn] <= map[xn][yn]){
map[xn][yn] = t + visited[xn][yn];
ch = visited[xn][yn];
visited[xn][yn] = -1;
dfs(xn, yn, t + ch);
visited[xn][yn] = ch;
}
}
}
}
}
A strange lift
#include <iostream>
#include <algorithm>
#include <stdlib.h>
using namespace std;
const int M = 1005;
int n;
bool visit[M];
int buttom[M],step[M];
int loc[M];
int judge( int x )
{
if( x >= 1 && x<=n )
return 1;
return 0;
}
int BFS( int start , int end )
{
int front , tail;
front = tail = 0;
loc[front++] = start;
while( front > tail ){
int x = loc[tail++];
if( x == end )
break;
int up,down;
up = x+buttom[x];
down = x-buttom[x];
if( !visit[up] && judge(up) ){
visit[up] = true;
step[up] = step[x]+1;
loc[front++] = up;
}
if( !visit[down] && judge(down) ){
visit[down] = true;
step[down] = step[x]+1;
loc[front++] = down;
}
}
return step[end];
}
int main( )
{
int start, end;
while( scanf("%d",&n) == 1 && n ){
scanf("%d%d",&start,&end);
for( int i=1 ; i<=n ; i++ ){
scanf("%d",&buttom[i]);
visit[i] = false;
step[i] = 0;
}
if( start == end )
printf("0\n");
else{
int ans;
ans = BFS( start , end );
if( ans == 0 )
printf("-1\n");
else
printf("%d\n",step[end]);
}
}
return 0;
}
Knight Moves
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
struct node
{
int x, y;
int step;
};
queue<node>q;
node s, next;
char a[3], b[3];
int sx, sy, ex, ey, visit[9][9];
int dx[8] = {2, -2, 2, -2, 1, -1, 1, -1}; //direcito of '日'
int dy[8] = {1, 1, -1, -1, 2, 2, -2, -2};
int check(int x, int y)
{
if(x < 1 || x > 8 || y < 1 || y > 8)
return 0;
else
return 1;
}
void BFS()
{
int i;
while(!q.empty()) //in cace of last time queue has elements
q.pop();
memset(visit, 0, sizeof(visit)); //initalization
s.x = sx; s.y = sy; s.step = 0; //start push in queue
q.push(s);
visit[sx][sy] = 1; //mark it was visited
while(!q.empty())
{
s = q.front();
q.pop();
if(s.x == ex && s.y == ey)
{
cout << "To get from " << a << " to "<< b
<< " takes " << s.step << " knight moves." << endl;
break;
}
for(i = 0; i < 8; i++)
{
next.x = dx[i] + s.x;
next.y = dy[i] + s.y;
next.step = s.step + 1;
if(!check(next.x, next.y))
continue;
if(!visit[next.x][next.y])
{
q.push(next);
visit[next.x][next.y] = 1;
}
}//end of direction for(...)
}//end of while(...)
}//end of BFS()
int main()
{
while(cin >> a >> b)
{
sx = a[0] - 'a' + 1;
sy = a[1] - '0';
ex = b[0] - 'a' + 1;
ey = b[1] - '0';
BFS();
}
return 0;
}
Nightmare
#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
int mp[10][10],m,n,Sx,Sy,Dx,Dy,flag,dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct point
{
int x,y,time,step;
};
void bfs(int x,int y)
{
int i;
point t,tt;
queue<point>Q;
t.x=x;t.y=y;t.step=0;t.time=6;
Q.push(t);
// memset(visit,0,sizeof(visit));
while(!Q.empty())
{
t=Q.front();
Q.pop();//printf("%d,%d\n",t.x,t.y);
for(i=0;i<4;i++)
{
tt.x=t.x+dir[i][0];tt.y=t.y+dir[i][1]; tt.step=t.step+1;tt.time=t.time-1;
// printf("\t%d,%d",tt.x,tt.y);
if(tt.x<1||tt.x>m||tt.y<1||tt.y>n||mp[tt.x][tt.y]==0||tt.time==0) continue;
if(mp[tt.x][tt.y]==3){printf("%d\n",tt.step);return;}
// printf("!\n");
if(mp[tt.x][tt.y]==4){
mp[tt.x][tt.y]=0;
tt.time=6;
// memset(visit,0,sizeof(visit));
}
// mp[tt.x][tt.y]=0;
Q.push(tt);
}
// system("pause");
}
printf("-1\n");
return;
}
int main()
{
int T,i,j;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&m,&n);
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&mp[i][j]);
if(mp[i][j]==2) Sx=i,Sy=j;
}
}
bfs(Sx,Sy);
}
return 0;
}
Hike on a Graph
#include <cstdio>
#include <string.h>
#include <queue>
using namespace std;
struct pos{int x,y,z;pos(int a,int b,int c){x=a,y=b,z=c;}};
int n,p1,p2,p3;
char map[60][60];
int vis[60][60][60];
/*
BFS 三个点,x->i仅当color[x][i]=color[y][z]
*/
int bfs(){
memset(vis,0,sizeof vis);
queue<pos> q;
q.push(pos(p1,p2,p3));
vis[p1][p2][p3]=1;
while(!q.empty()){
pos p=q.front();q.pop();
if(p.x==p.y&&p.y==p.z)return vis[p.x][p.y][p.z]-1;
for(int i=1;i<=n;i++){
if(map[p.x][p.y]==map[p.z][i]&&!vis[p.x][p.y][i]){
vis[p.x][p.y][i]=vis[p.x][p.y][p.z]+1;
q.push(pos(p.x,p.y,i));
}
if(map[p.z][p.x]==map[p.y][i]&&!vis[p.x][i][p.z]){
vis[p.x][i][p.z]=vis[p.x][p.y][p.z]+1;
q.push(pos(p.x,i,p.z));
}
if(map[p.y][p.z]==map[p.x][i]&&!vis[i][p.y][p.z]){
vis[i][p.y][p.z]=vis[p.x][p.y][p.z]+1;
q.push(pos(i,p.y,p.z));
}
}
}
return -1;
}
int main(){
while(scanf("%d",&n),n){
scanf("%d%d%d",&p1,&p2,&p3);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf(" %c",&map[i][j]);
int r=bfs();
if(r==-1)printf("impossible\n");
else printf("%d\n",r);
}
return 0;
}
非常可乐
/*
首先剪枝是 如果s是奇数必然不行。
一看到要求最少的步数就知道用bfs了
我们用vis标记状态
每个状态有三个整数组成 表示这三个杯子里的可乐数量
然后对每个状态的递推是 6种 也就是3!种。从一个到到另一个 再标记 入队
*/
#include<iostream>
#include<queue>
#include<cstring>
#define N 105
using namespace std;
bool flag;
int s,n,m;
struct point
{
int x,y,z;
int step;
};
bool visited[N][N][N];
point s_pos;
int ok(point t) //结束状态
{
if((t.x==t.y&&t.z==0)||(t.x==t.z&&t.y==0)||(t.y==t.z&&t.x==0))
return 1;
return 0;
}
void bfs()
{
memset(visited,0,sizeof(visited));
visited[s][0][0]=1;
s_pos.x=s; s_pos.y=0; s_pos.z=0; s_pos.step=0;
queue<point>Q;
Q.push(s_pos);
while(!Q.empty())
{
point p;
int t;
point temp=Q.front();
Q.pop();
if(ok(temp))
{
flag=1;
cout<<temp.step<<endl;
return ;
}
if(temp.x>0)
{
if(temp.y<n)
{
t=n-temp.y;
p.z=temp.z;
p.step=temp.step+1;
if(temp.x>t)
{ p.x=temp.x-t; p.y=n; }
else
{ p.x=0; p.y=temp.y+temp.x; }
if(!visited[p.x][p.y][p.z])
{
visited[p.x][p.y][p.z]=1;
Q.push(p); //x->y
}
}
if(temp.z<m)
{
t=m-temp.z;
p.y=temp.y;
if(temp.x>t)
{ p.x=temp.x-t; p.z=m;p.step=temp.step+1; }
else
{ p.x=0; p.z=temp.z+temp.x; p.step=temp.step+1; }
if(!visited[p.x][p.y][p.z])
{
visited[p.x][p.y][p.z]=1;
Q.push(p);
} //x->z
}
}
if(temp.y>0)
{
if(temp.x<s)
{
t=s-temp.x;
p.z=temp.z;
if(temp.y>t)
{ p.y=temp.y-t; p.x=s; p.step=temp.step+1; }
else
{ p.y=0; p.x=temp.y+temp.x; p.step=temp.step+1; }
if(!visited[p.x][p.y][p.z])
{
visited[p.x][p.y][p.z]=1;
Q.push(p);
} //y->x
}
if(temp.z<m)
{
t=m-temp.z;
p.x=temp.x;
if(temp.y>t)
{ p.y=temp.y-t; p.z=m;p.step=temp.step+1; }
else
{ p.y=0; p.z=temp.z+temp.y; p.step=temp.step+1; }
if(!visited[p.x][p.y][p.z])
{
visited[p.x][p.y][p.z]=1;
Q.push(p);
} //y->z
}
}
if(temp.z>0)
{
if(temp.x<s)
{
t=s-temp.x;
p.y=temp.y;
if(temp.z>t)
{ p.z=temp.z-t; p.x=s;p.step=temp.step+1; }
else
{ p.z=0; p.x=temp.z+temp.x;p.step=temp.step+1; }
if(!visited[p.x][p.y][p.z])
{
visited[p.x][p.y][p.z]=1;
Q.push(p);
} //z->x
}
if(temp.y<n)
{
t=n-temp.y;
p.x=temp.x;
if(temp.z>t)
{ p.z=temp.z-t; p.y=n;p.step=temp.step+1; }
else
{ p.z=0; p.y=temp.z+temp.y; p.step=temp.step+1;}
if(!visited[p.x][p.y][p.z])
{
visited[p.x][p.y][p.z]=1;
Q.push(p);
} //z->y
}
}
}
}
int main()
{
while(cin>>s>>n>>m,s+n+m)
{
flag=0;
bfs();
if(!flag)
cout<<"NO"<<endl;
}
return 0;
}
Treasure of the Chimp Island
/*
题意:给最大100*100的地图,$代表财宝,*表示不可达,. 表示走过不需要花费,
1~9表示走过需要花费1~9,边界格子为* ,#(表示从此进入可以带0个
炸药)或A~Z(表示从此进入可以带1~26个炸药),现在一个人可以从边界非*处进入,
最小到达$位置的最小花费是多少。
题解:如果考虑枚举起点的话,最坏情况边界全部为起点,
这样至少100*100*100*100的复杂度就悲剧了。 所以想从$开始bfs 最短路,
dis[ i ][ j ][ k ]表示
到达[ i , j ]点已经用k个炸弹的最小花费,注意边界点不入队列即可。
*/
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
#define MIN(a , b) ((a) < (b) ? (a) : (b))
using namespace std;
const int inf = 1 << 29;
const int maxn = 102;
const int maxm = 27;
const int move[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
struct ddd
{
int x,y,use;
int val;
ddd(){}
ddd(int xx,int yy,int uu,int vv)
{
x = xx;
y = yy;
use = uu;
val = vv;
return;
}
bool operator < (const ddd &other) const
{
return val > other.val;
}
};
priority_queue <ddd> Q;
int dis[maxn][maxn][maxm];
bool vis[maxn][maxn][maxm];
char map[maxn][maxn];
int m,n;
void init()
{
memset(vis,false,sizeof(vis));
while(!Q.empty()) Q.pop();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
for(int k=0;k<maxm;k++)
{
dis[i][j][k] = inf;
}
if(map[i][j] == '$')
{
dis[i][j][0] = 0;
Q.push(ddd(i,j,0,0));
map[i][j] = '.';
}
}
}
return;
}
bool judge(int x,int y)
{
if(x >= 0 && y >= 0 && x < n && y < m && map[x][y] != '*')
{
return true;
}
return false;
}
int bound(int x,int y)
{
if(x == 0 || y == 0 || x == n-1 || y == m-1)
{
if(map[x][y] == '#') return 0;
else if(map[x][y] >= 'A' && map[x][y] <= 'Z') return map[x][y] - 'A' + 1;
return -1;
}
return -1;
}
void bfs()
{
int res = inf;
ddd cur;
while(!Q.empty())
{
cur = Q.top();
Q.pop();
if(vis[cur.x][cur.y][cur.use]) continue;
vis[cur.x][cur.y][cur.use] = true;
for(int i=0;i<4;i++)
{
int tx = cur.x + move[i][0];
int ty = cur.y + move[i][1];
if(judge(tx , ty))
{
int d = bound(tx , ty);
if(d >= 0)
{
if(d >= cur.use) res = MIN(res , cur.val);
continue;
}
if(map[tx][ty] == '.')
{
if(vis[tx][ty][cur.use] == false && dis[tx][ty][cur.use] > cur.val)
{
dis[tx][ty][cur.use] = cur.val;
Q.push(ddd(tx , ty , cur.use , cur.val));
}
}
else
{
int cost = map[tx][ty] - '0';
if(vis[tx][ty][cur.use] == false && dis[tx][ty][cur.use] > cur.val + cost)
{
dis[tx][ty][cur.use] = cur.val + cost;
Q.push(ddd(tx , ty , cur.use , cur.val + cost));
}
if(cur.use < 26 && vis[tx][ty][cur.use + 1] == false && dis[tx][ty][cur.use + 1] > cur.val)
{
dis[tx][ty][cur.use + 1] = cur.val;
Q.push(ddd(tx , ty , cur.use + 1 , cur.val));
}
}
}
}
}
if(res == inf) puts("IMPOSSIBLE");
else printf("%d\n",res);
return;
}
int main()
{
while(true)
{
n = 0;
while(gets(map[n]))
{
if(map[n][0] == '-') return 0;
if(map[n][0] == '\0') break;
n++;
}
m = strlen(map[0]);
init();
bfs();
}
return 0;
}