SDUT oj 3005 打怪升级(记忆化搜索)

比赛的时候一直在纠结乘2的数目很大怎么办,数组开不开啊。。。后来才发现自己傻了啊,那个数目最大不会超过10啊,这个力量上限是100啊。。。。

其他的就是记忆化搜索啊,还有就是加一点力量的瓶子当时就要用上。

打怪升级

Time Limit: 1000ms   Memory limit: 262144K  有疑问?点这里^_^

题目描述

对于多数 RPG 游戏来说,除了剧情就是打怪升级。本题的任务是用最短的时间取得所有战斗的胜利。这些战斗必须按照特定的顺序进行,每打赢一场,都可能会获得一些补药,用来提升力量。本题只有两种补药:“加 1 药” 和“乘 2 药” ,分别让你的力量值加 1 和乘以 2。战斗时间取决于你的力量。每场战斗可以用 6 个参数描述: p1, p2, t1, t2, w1, w2。如果你的力量小于 p1,你将输掉战斗;如果你的力量大于 p2,需要 t2秒赢得战斗;如果力量位于 p1 和 p2(包括 p1 和 p2),战斗时间从 t1 线性递减到 t2。比如 p1=50, p2=75, t1=40, t2=15,你的力量为 55,则战斗获胜需要 35 秒。注意,战斗时间可能不是整数。最后两个参数 w1 和 w2 分别表示战斗胜利后获得的“加 1 药” 和“乘 2 药” 的数量。 注意,你不一定要立刻使用这些补药,可以在需要的时候再用,但不能在战斗中使用补药。按顺序给出每场战斗的参数,输出赢得所有战斗所需的最短总时间。战斗必须按顺序进行,且不能跳过任何一场战斗。

输入

输入最多包含 25 组测试数据。每组数据第一行为两个整数 n 和 p( 1<=n<=1000, 1<=p<=100),即战斗的场数和你的初始力量值。以下 n 行每行 6 个整数 p1, p2, t1, t2, w1, w2( 1<=p11<=p1<p2<=100, 1<=t2<t1<=100,0<=w1,w2<=10),按顺序给出各场战斗的参数,输入结束标志为n=p=0

输出

对于每组数据,输出最短总时间(单位:秒),保留两位小数。如果无解,输出“Impossible”(不含引号)。

示例输入

1 55
50 75 40 15 10 0
2 55
50 75 40 15 10 0
50 75 40 15 10 0
3 1
1 2 2 1 0 5
1 2 2 1 1 0
1 100 100 1 0 0
1 7
4 15 35 23 0 0
1 1
2 3 2 1 0 0
0 0

示例输出

35.00
60.00
41.00
31.73
Impossible

提示

#include <set>
#include <map>
#include <queue>
#include <math.h>
#include <vector>
#include <string>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <cctype>
#include <algorithm>

using namespace std;

const int maxn = 1010;
const double INF = 100000000.0;

struct node
{
    int p1, p2, t1, t2, w1, w2;
}f[maxn];
int n;
double dp[maxn][110][15];

double distime(node a, int x)
{
    if(x >= a.p2) return a.t2*1.0;
    double x1 = a.p1*1.0;
    double y1 = a.t1*1.0;
    double x2 = a.p2*1.0;
    double y2 = a.t2*1.0;
    double x3 = x*1.0;
    return (x3*((y1-y2)/(x1-x2)) + (y1-x1*((y1-y2)/(x1-x2))));
}

double dfs(int x, int w, int num)
{
    if(x > n) return 0;
    if(dp[x][w][num] > -1.0) return dp[x][w][num];
    if(w < f[x].p1)
    {
        while(w < f[x].p2 && num)
        {
            w = min(100, w*2);
            num--;
        }
    }
    if(w < f[x].p1)
    {
        dp[x][w][num] = INF;
        return dp[x][w][num];
    }
    dp[x][w][num] = INF;
    for(int i = 0; i <= num; i++)
        dp[x][w][num] = min(dp[x][w][num], distime(f[x], w<<i)+dfs(x+1, min((w<<i)+f[x].w1, 100), min(10, num-i+f[x].w2)));
    return dp[x][w][num];
}

int main()
{
    int p;
    while(~scanf("%d %d",&n, &p))
    {
        if(!n && !p) break;
        for(int i = 1; i <= n; i++) scanf("%d %d %d %d %d %d",&f[i].p1, &f[i].p2, &f[i].t1, &f[i].t2, &f[i].w1, &f[i].w2);
        memset(dp, -1, sizeof(dp));
        dfs(1, p, 0);
        double Min = INF;
        for(int i = 1; i <= 100; i++) Min = min(dp[1][i][0], Min);
        if(Min == INF) cout<<"Impossible"<<endl;
        else printf("%.2lf\n",Min);
    }
}
时间: 2024-10-11 05:41:41

SDUT oj 3005 打怪升级(记忆化搜索)的相关文章

SDUT oj 3005 打怪升级(内存搜索)

当比赛一直纠缠骑2如何做一个非常大的数量,数组不开啊...后来他们发现自己很傻啊,该数不超过最大10什么,这个上限就是力量100什么.. .. 其它的就是记忆化搜索啊,还有就是加一点力量的瓶子当时就要用上. 打怪升级 Time Limit: 1000ms   Memory limit: 262144K  有疑问?点这里^_^ 题目描写叙述 对于多数 RPG 游戏来说,除了剧情就是打怪升级.本题的任务是用最短的时间取得全部战斗的胜利.这些战斗必须依照特定的顺序进行,每打赢一场.都可能会获得一些补药

[Swust OJ 409]--小鼠迷宫问题(BFS+记忆化搜索)

题目链接:http://acm.swust.edu.cn/problem/409/ Time limit(ms): 1000 Memory limit(kb): 65535 Description 小鼠a与小鼠b身处一个m×n的迷宫中,如图所示.每一个方格表示迷宫中的一个房间.这m×n个房间中有一些房间是封闭的,不允许任何人进入.在迷宫中任何位置均可沿上,下,左,右4个方向进入未封闭的房间.小鼠a位于迷宫的(p,q)方格中,它必须找出一条通向小鼠b所在的(r,s)方格的路.请帮助小鼠a找出所有通

【算法学习笔记】55.DFS 记忆化搜索 SJTU OJ 1063 小M爱滑雪

Description 小M超级喜欢滑雪~~ 滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当小M滑到坡底,便不得不再次走上坡或者等待升降机来载你.小M想知道滑雪场中最长底的滑坡.滑雪场由一个二维数组给出.数组的每个数字代表点距离水平面的相对距离.下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 小M可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小.在上面的例子中,一条可滑行的

SDUT 2893-B(DP || 记忆化搜索)

B Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 有n块地板排成一条直线,从左到右编号为1,2,3. . . n-1,n,每块地板上有一个权值w.现在要小B用这n块地板玩一个游戏. 小B可以选择任意一块地板作为起点,然后向右跳K次,每次最多可以跳5个格子(设起跳点地板编号为x,落地点为y,y-x <= 5).每踩在一块地板上,小B的得分sum += wi ,小B每次只能踩一块地板,开始时sum = 0.现在请你编写一个程序求

[期望dp+记忆化搜索] light oj 1038 Race to 1 Again

题意: 给一个数n,每次随机选它的一个约数去除n,直到除到1为止,问除的次数的期望. 思路: E[n]= E[n/a[1]]/cnt+E[n/a[2]]/cnt+...+E[n/a[n]]/cnt+1 a[i]为n的约数,cnt为约数的个数. 显然a[i]=1  则(1-1/cnt)E[n]=E[n/a[2]]/cnt+...+E[n/a[n]]/cnt+1 记忆化搜索就ok了~ 代码: #include"cstdlib" #include"cstdio" #inc

动态规划①——记忆化搜索

首先的首先,必须明白动态规划(DP)以后很有用很有用很有用很有用……首先的其次,必须明白:动规≍搜索=枚举 一.最简单的记忆化搜索(应该可以算DP) 题目(来自洛谷OJ)http://www.luogu.org/problem/show?pid=1434# [不麻烦大家自己找了]题目描述 DescriptionMichael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最

uva10285 Longest Run on a Snowboard(dp之记忆化搜索 )

10285 Longest Run on a Snowboard Michael likes snowboarding. That's not very surprising, since snowboarding is really great. The bad thing is that in order to gain speed, the area must slide downwards. Another disadvantage is that when you've reached

硬币找零-记忆化搜索(DP动态规划)

硬币找零 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 在现实生活中,我们经常遇到硬币找零的问题,例如,在发工资时,财务人员就需要计算最少的找零硬币数,以便他们能从银行拿回最少的硬币数,并保证能用这些硬币发工资. 我们应该注意到,人民币的硬币系统是 100,50,20,10,5,2,1,0.5,0.2,0.1,0.05, 0.02,0.01 元,采用这些硬币我们可以对任何一个工资数用贪心算法求出其最少硬币数. 但不幸的是: 我们可能没有这样一种好的硬币系统, 因此

换根dp+暴力+预处理+记忆化搜索——cf1292C好题!

/** 给定一棵树,要求给树边赋值[0,n-2],每个值只能使用一次 S = mex(u,v), mex(u,v)是u-v路径上没有出现过的编号最小的值 问使得S最大的赋值方式 由于很难直接统计答案,所以考虑统计每条边的贡献 包含(0)路径的贡献tot1是其左右子树size的乘积 包含(0,1)的路径的贡献tot2是其左右子树的size乘积 ...依次类推 显然:只包含(1,2)这样的路径是没有贡献的 那么原问题转化为如何分配[0,n-2],使得最后的乘积和最大 dp[u][v]表示路径(u,v