分析:之前的一道模拟赛题是dp+dfs,这道题是dp+bfs.

我们设f[stu][i][j]为当前状态为stu,走到(i,j)的答案,考虑怎么设计stu,每个人的状态有3种:要么在原地,要么被背着,要么已经到了终点,那么用一个3进制数保存就可以了.

下面考虑怎么转移,直接递推肯定是不对的,dfs也不行,只能bfs了.我们每次可以选择不走,或者如果当前点有人就背起来,或者到了终点就放下所有人或者放下所有使速度变慢的人,写好几次转移就过了.

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std;
const int inf = 0x7ffffff; int n, m, k, top, sx, sy, tx, ty, a[][], speed[], f[][][], dx[] = { , -, , }, dy[] = { , , , - },flag[];
char name[][],s[][]; struct node
{
int x, y, zhuangtai;
}; int jisuan(int stu)
{
int tot = ,sped = k;
memset(flag, , sizeof(flag));
while (stu)
{
tot++;
flag[tot] = stu % ;
stu /= ;
}
for (int i = ; i <= top; i++)
if (flag[i] == )
sped += speed[i];
if (sped < )
sped = ;
return sped;
} bool judge(int x, int y)
{
if (x >= && x <= n && y >= && y <= m)
return true;
return false;
} int bei(int stu, int x, int y)
{
int cur, tot = ;
for (int i = ; i <= top; i++)
if (s[x][y] == name[i][])
{
cur = i;
break;
}
memset(flag, , sizeof(flag));
while (stu)
{
tot++;
flag[tot] = stu % ;
stu /= ;
}
if (flag[cur])
return ;
flag[cur] = ;
for (int i = top; i >= ; i--)
stu = stu * + flag[i];
return stu;
} int fang1(int stu, int x, int y)
{
memset(flag, , sizeof(flag));
int tot = ;
while (stu)
{
tot++;
flag[tot] = stu % ;
stu /= ;
}
for (int i = ; i <= top; i++)
if (flag[i] == )
flag[i] = ;
for (int i = top; i >= ; i--)
stu = stu * + flag[i];
return stu;
} int fang2(int stu, int x, int y)
{
int tot = ;
memset(flag, , sizeof(flag));
while (stu)
{
tot++;
flag[tot] = stu % ;
stu /= ;
}
for (int i = ; i <= top; i++)
if (flag[i] == && speed[i] > )
flag[i] = ;
for (int i = top; i >= ; i--)
stu = stu * + flag[i];
return stu;
} int qpow(int a, int b)
{
int res = ;
while (b)
{
if (b & )
res *= a;
a *= a;
b >>= ;
}
return res;
} void bfs()
{
queue <node> q;
node temp;
temp.x = sx;
temp.y = sy;
temp.zhuangtai = ;
q.push(temp);
while (!q.empty())
{
node u = q.front();
q.pop();
int sudu = jisuan(u.zhuangtai),x = u.x,y = u.y;
//printf("%d %d %d\n", sudu, x, y);
for (int i = ; i < ; i++)
{
int nx = x + dx[i], ny = y + dy[i];
if (judge(nx, ny))
{
//只移动
if (s[nx][ny] != '#' && f[u.zhuangtai][nx][ny] > f[u.zhuangtai][x][y] + sudu)
{
f[u.zhuangtai][nx][ny] = f[u.zhuangtai][x][y] + sudu;
node temp;
temp.x = nx;
temp.y = ny;
temp.zhuangtai = u.zhuangtai;
q.push(temp);
}
//背人
if (s[nx][ny] >= 'A' && s[nx][ny] <= 'Z')
{
int stu = bei(u.zhuangtai, nx, ny);
if (f[stu][nx][ny] > f[u.zhuangtai][x][y] + sudu)
{
f[stu][nx][ny] = f[u.zhuangtai][x][y] + sudu;
node temp;
temp.zhuangtai = stu;
temp.x = nx;
temp.y = ny;
q.push(temp);
}
}
//放人
if (s[nx][ny] == 't')
{
int stu1 = fang1(u.zhuangtai, nx, ny);
int stu2 = fang2(u.zhuangtai, nx, ny);
if (f[stu1][nx][ny] > f[u.zhuangtai][x][y] + sudu)
{
f[stu1][nx][ny] = f[u.zhuangtai][x][y] + sudu;
node temp;
temp.zhuangtai = stu1;
temp.x = nx;
temp.y = ny;
q.push(temp);
}
if (f[stu2][nx][ny] > f[u.zhuangtai][x][y] + sudu)
{
f[stu2][nx][ny] = f[u.zhuangtai][x][y] + sudu;
node temp;
temp.zhuangtai = stu2;
temp.x = nx;
temp.y = ny;
q.push(temp);
}
}
}
}
}
} int main()
{
scanf("%d%d%d", &n, &m, &k);
for (int i = ; i <= n; i++)
{
scanf("%s", s[i] + );
for (int j = ; j <= m; j++)
{
if (s[i][j] == 's')
{
sx = i;
sy = j;
}
else
{
if (s[i][j] == 't')
{
tx = i;
ty = j;
}
else
{
if (s[i][j] >= 'A' && s[i][j] <= 'Z')
top++;
}
}
}
}
for (int i = ; i <= top; i++)
scanf("%s%d", name[i], &speed[i]);
for (int i = ; i <= ; i++)
for (int j = ; j <= ; j++)
for (int l = ; l <= ; l++)
f[i][j][l] = inf;
f[][sx][sy] = ;
bfs();
printf("%d\n", f[qpow(, top) - ][tx][ty]); return ;
}

noip模拟赛 蒜头君救人的更多相关文章

  1. noip模拟赛 蒜头君的兔子

    分析:直接暴力算有30分,像斐波那契那样推式子算有60分,如果想要得到100分就要用一种数列题的常见优化--矩阵了. 当前的兔子数和十年内的兔子数有关,我们需要1个1*11的矩阵,来记录当前为0岁.1 ...

  2. noip模拟赛 蒜头君的排序

    分析:其实就是求m个区间的逆序对个数,题目真的是明摆着让我们用莫队算法,套用树状数组就可以了. 具体怎么转移呢?如果移动R,那么对区间[l,r]有影响的是R左边的元素,我们只需要看有多少在R左边比a[ ...

  3. noip模拟赛 蒜头君的坐骑

    分析:标准的棋盘dp问题. 如果没有技能,那么就很好做了,相当于传纸条的做法.有了技能的限制,我们就要加上一维表示用了多少次技能,这个时候转移就要用到dfs了,而且不能用填表法,要用刷表法,从当前位置 ...

  4. noip模拟赛 蒜头君的树

    分析:这道题问的是树上整体的答案,当然要从整体上去考虑. 一条边对答案的贡献是这条边一端连接的点的个数*另一端连接的点的个数*边权,可以用一次dfs来统计答案,之后每次更改操作在原答案的基础上增减就好 ...

  5. noip模拟赛 蒜头君打地鼠

    分析:直接一个一个地去暴力枚举分数比较少,我们需要一种比较快的统计一定空间内1的数量,标准做法是前缀和,但是二维前缀和维护的是一个矩形内的值,这个是旋转过的该怎么办?可以把图旋转45°,不过这样比较考 ...

  6. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  7. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  8. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  9. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

随机推荐

  1. bzoj 1592: [Usaco2008 Feb]Making the Grade 路面修整【dp】

    因为是单调不降或单调不升,所以所有的bi如果都是ai中出现过的一定不会变差 以递增为例,设f[i][j]为第j段选第i大的高度,预处理出s[i][j]表示选第i大的时,前j个 a与第i大的值的差的绝对 ...

  2. 论文翻译-SELF TRAINING AUTONOMOUS DRIVING AGENT

    文献地址 链接:https://pan.baidu.com/s/1gHrpnOf1FXLp9u8OJ2-oCg 提取码:y2w6 作者 Shashank Kotyan, Danilo Vasconce ...

  3. ACM_Scramble Sort

    Scramble Sort Time Limit: 2000/1000ms (Java/Others) Problem Description: In this problem you will be ...

  4. 转 MySQL实验(三) 过程式数据库对象的使用

    转 http://blog.csdn.net/anne999/article/details/70432558

  5. 牛客网-3 网易编程题(1拓扑&2二叉树的公共最近祖先&3快排找第K大数)

    1. 小明陪小红去看钻石,他们从一堆钻石中随机抽取两颗并比较她们的重量.这些钻石的重量各不相同.在他们们比较了一段时间后,它们看中了两颗钻石g1和g2.现在请你根据之前比较的信息判断这两颗钻石的哪颗更 ...

  6. [ HDOJ 3826 ] Squarefree number

    \(\\\) \(Description\) \(T\)组数据,每次给出一个正整数 \(N\) ,判断其是否能被任意一个完全平方数整除. \(T\le 20,N\le 10^{18}\) \(\\\) ...

  7. Django--4、认证系统

    cookie与session 概念 因http协议无法保存状态,但是又需要保存状态,所以有了cookie.它不属于http协议范畴 工作原理:相当于一段标识数据.在访问服务器产生标识内容(cookie ...

  8. MySQL 帮助类 MySQLHelper

    /// <summary> /// MySqlHelper操作类 /// </summary> public sealed partial class MySQLHelper ...

  9. TortoiseSVN客户端不能记住用户名和密码

    TortoiseSVN客户端重新设置用户名和密码 在第一次使用TortoiseSVN从服务器CheckOut的时候,会要求输入用户名和密码,这时输入框下面有个选项是保存认证信息,如果选了这个选项,那么 ...

  10. Knockout 实例

    定义见:http://baike.baidu.com/item/Knockout/18611883#viewPageContent 此处仅列举一个小例子 <p> <select da ...