思路:这题的贪心大概就是如果魔法值大于等于10,就立即使用魔法。然而这个贪心好像对当前的选择没什么帮助,于是我预处理了魔法值为0~9的所有情况。
定义的结构体:
struct node{
int tim; //超过的时间
int dis; //走过距离
int re; //剩余魔法值
}goal[maxn];
初始魔法值是i,goal[i].tim表示完全使用魔法超过跑步的最短需要的时间(包含两者距离相等),goal[i].dis表示超过时已经移动的距离,goal[i].re表示超过时剩余的魔法值。
在知道了所有goal的情况下,我们就能根据当前剩余时间来决定是否要存储魔法值或则直接跑步。
注意:可能会出现使用魔法超过s,但是跑步可以在更短的时间内超过s,即使使用魔法移动的距离超过跑步的距离,这时我们应该选择跑步,因为题目要求:在能够逃离时,输出最少的时间。
AC代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <bitset>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 10 + 5;
struct node{
int tim; //超过的时间
int dis; //走过距离
int re; //剩余魔法值
}goal[maxn];
void init(int t) {
for(int i = 0; i < 10; ++i) {
goal[i].tim = inf;
int d1 = 0, d2 = 0, m = i;
for(int j = 1; j <= t; ++j) {
d1 += 17;
if(m >= 10) {
m -= 10;
d2 += 60;
}
else m += 4;
if(d2 >= d1) {
goal[i].tim = j;
goal[i].dis = d2;
goal[i].re = m;
break;
}
}
}
}
int main() {
int m, s, t;
while(scanf("%d%d%d", &m, &s, &t) == 3) {
init(t);
int dis = 0;
int tim;
for(tim = 1; tim <= t;) {
if(m >= 10) {
m -= 10;
dis += 60;
tim++;
}
else {
int r = t - tim + 1;
if(r >= goal[m].tim) {
int d = (s-dis)/17;
if((s-dis)%17) d++;
if(d <= goal[m].tim) {
tim += d;
dis = s;
break;
}
tim += goal[m].tim;
dis += goal[m].dis;
m = goal[m].re;
}
else {
tim++;
dis += 17;
}
}
if(dis >= s) break;
}
if(dis < s) {
printf("No\n%d\n", dis);
}
else printf("Yes\n%d\n", tim-1);
}
return 0;
}
如有不当之处欢迎指出!