Description 题目描述
上帝需要创造一位战士去消灭撒旦,这位战士必须要穿过恶魔城才能与撒旦决斗。恶魔城内有 M M M条连接 N N N个路口(从 1 1 1到 N N N编号)的街道,每一条街道都是单向的(也就是说你不能逆着该街道指定的方向走),并且在城内无论怎么走都不可能走回原来走过的地方。开始的时候,战士的生命力(HP)为INITHP、站在 1 1 1号路口,而撒旦在第 N N N号路口等待着他。每一条街道上都有许多魔鬼,但是也有一些街道已经被上帝派去的天使占领了。当战士经过连接 i i i号向 j j j号路口的街道时,如果占领该街道的是恶魔,那么他的HP先加倍然后减少 L [ i , j ] L[i,j] L[i,j],我们记为 A [ i , j ] = − L [ i , j ] A[i,j]=-L[i,j] A[i,j]=−L[i,j];如果占领该街道的是天使,那么他的HP就会先加倍然后增加 L [ i , j ] L[i,j] L[i,j],我们记为 A [ i , j ] = + L [ i , j ] A[i,j]=+L[i,j] A[i,j]=+L[i,j];如果该街道不存在,那么 A [ i , j ] = 0 A[i,j]=0 A[i,j]=0。如果某一时刻战士的 H P ≤ 0 HP≤0 HP≤0,那么他会死亡。因为这个战士将非常无敌,当他见到撒旦的时候只要还活着,就能一口气把撒旦消灭,所以上帝不希望让他的INITHP过高。
任务:
给定 N , A [ 1.. N , 1.. N ] N,A[1..N,1..N] N,A[1..N,1..N],求最小的INITHP,使这个战士能够活着见到撒旦。
Input 输入
文件第一行有一个正整数 N N N,下面跟着的第 i i i行第 j j j个数为 A [ i , j ] A[i,j] A[i,j](绝对值不超过 10000 10000 10000的整数)。
Output 输出
输出所求最小的INITHP。
Sample Input 样例输入
4
0 -4 0 -10
0 0 +3 0
0 0 0 -14
0 0 0 0
Sample Output 样例输出
4
Limits 限制
3 ≤ N ≤ 100 3 ≤ N ≤ 100 3≤N≤100
Time Limit : 1 s 1s 1s & Memory Limit : 128 M B 128MB 128MB
问道最小代价,还不能太高,SPFA+二分的思路已经出来了…
先写个试试
#include <queue>
#include <cstdio>
#include <climits>
#include <cstring>
#define MAXN 105
using namespace std;
int a[MAXN][MAXN];
long long dis[MAXN];
int n,i,j;
queue <int> q;
bool spfa(int src,long long hp)
{
while (!q.empty()) q.pop();
memset(dis,0,sizeof(dis));
q.push(src);dis[src]=hp;
while (!q.empty())
{
int u=q.front();
q.pop();
for (int i=1;i<=n;i++)
{
if (a[u][i]==0) continue;
if (dis[u]*2+a[u][i]>0) //类似松弛操作,能走就走
{
if (i==n) return true;
q.push(i);
dis[i]=dis[u]*2+a[u][i];
}
}
}
return false;
}
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
scanf("%d",&a[i][j]);
for (long long hp=1;hp<=10000;hp++)
{
if (spfa(1,hp))
{
printf("%d",hp);
return 0;
}
}
return 0;
}
交完之后发现WA
2
2
2个点,不超时。
检查,发现最后两个点数据太大了,long long的dis数组炸了…
(我要(和谐~~)人了…)
既然
d
i
s
dis
dis炸了,就不用了…
转战DFS+二分
上代码
Code
成功A掉
跑图DFS还真快…