UVALive 6908 广搜

题意很有意思,给了n段路,每段路长度不同,你有一辆车最多可以提供E的能量,你的车有四个档,最多换k次档

Assist Level    0  1  2  3 

Assist Power  0  4  8 11

0档花费能量0,走的路程长度为0,1档花费1能量,走得最大路程为4.... ,每段路用一个档,如果这个档不能使你走完这段路,那么只能自己蹬,如果超过这段路长度,超过部分不计算到下一段路,意味着下一段路重算,问你蹬车的最短路程是多少

最多1000段路,最多换10次档,最大提供能量为50,那么最多的状态为1000*10*50*4 =2e6,搜索所有状态的话2m也够,但是在搜索过程中肯定会挂掉很多状态,这些状态到中途夭折,所以能走到第n段路的状态肯定小于2e6,所以可以广搜,由此总结,可以用状态表示的都可以进行搜索枚举出来,只要状态少,在时间允许内,一般1e6,

d[i][k][e][l]=cost  ,表示走到底i段路剩余k次机会,剩余e能量用的事l档的最短蹬车路程。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
using namespace std;
const int maxn=1005,inf=0x3f3f3f3f;
int n,k,e;
int a[maxn];
int d[maxn][11][51][4],vis[maxn][11][51][4];
int pow[4]= {0,4,8,11};
int ans;
struct node
{
    int pos,k,e,l;
};
void bfs()
{
    queue<node>que;
    memset(vis,0,sizeof(vis));
    memset(d,inf,sizeof(d));
    d[0][k][e][0]=0;
    vis[0][k][e][0]=1;
    node s;
    s.pos=0;
    s.k=k;
    s.e=e;
    s.l=0;
    que.push(s);
    int cost;
    while(!que.empty())
    {
        node now=que.front();
        que.pop();
        int &cur=d[now.pos][now.k][now.e][now.l];
        if(now.pos==n)
        {
            ans=min(cur,ans);
            continue;
        }
        //vis[now.pos][now.k][now.e][now.l]=0;
        if(now.k>0)
        {
            for(int i=0; i<4; i++)
            {

                if(i==now.l||now.e<i)///可用能量小于花费肯定不行,不换挡的情况后面讨论
                    continue;
                    node temp=now;
                temp.pos++;
                temp.k--;
                temp.e-=i;
                temp.l=i;
                int &next=d[temp.pos][temp.k][temp.e][temp.l];
                cost=max(0,a[temp.pos]-pow[temp.l]);
                if(next>cur+cost)
                {
                    next=cur+cost;
                    if(vis[temp.pos][temp.k][temp.e][temp.l]==0)
                    {
                        que.push(temp);
                        vis[temp.pos][temp.k][temp.e][temp.l]=1;
                    }
                }
            }

        }
        /// 不换挡,
        node temp=now;
        temp.pos++;
        if(temp.e<temp.l)///能量不够了,直接变成0 挡,不用花费,直接蹬
           temp.k=0, temp.e=0,temp.l=0;
        else            /// 能量足够,继续用此挡前行
            temp.e-=temp.l;
        cost=max(0,a[temp.pos]-pow[temp.l]);
        int &next=d[temp.pos][temp.k][temp.e][temp.l];
        if(next>cur+cost)
        {
            next=cur+cost;
            if(vis[temp.pos][temp.k][temp.e][temp.l]==0)
            {
                que.push(temp);
                vis[temp.pos][temp.k][temp.e][temp.l]=1;
            }
        }
    }

}
int main()
{
    int T;
    scanf("%d",&T);
    for(int cas=1; cas<=T; cas++)
    {
        scanf("%d%d%d",&n,&k,&e);
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        ans=inf;
        bfs();
        printf("Case #%d: %d\n",cas,ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值