hdu4784 Dinner Coming Soon BFS

        在k个平行空间中,n个点,由m条有向边连接起来,每条边有一个时间花费和金钱花费,同时,在每个点上,可以跳转到(ki+1)%k 的空间里,不同空间的边权值不变。另外,在每到达某个空间的某个顶点时,可以买一包盐,卖一包盐,或者什么也不做,买卖的时间不考虑。相同的顶点在不同的空间中盐的价格也不一定相同..现在给定顶点数n,边数m,盐的最大携带量b,空间数k,初始的金钱r,规定的时间t,问怎么走可以在t时间内从1到达n,并且使到达n时身上的金钱尽可能大。初始时身上一包盐也没有,并且只有在空间0的时候,才能访问顶点1和n,并且一旦到达顶点n,这个过程就要结束......

        很绕口的题目= =....读清楚题意的话首先很容易想到spfa..现场赛的时候估计时间空间给的比较宽松,的确有队伍用spfa过了,但也有被卡常数的..hdoj上spfa估计就不太好过了..时间卡的太近。我是直接写了一个bfs,记录dp【id】【b】【k】【t】,表示在顶点id,身上有b包盐,空间k,还剩t分钟的时间时,身上最多能有多少钱,刚开始写spfa,需要反复的进出队列,所以很悲剧的TLE了。要控制每个状态进出队列一次,又发现有些状态明明可以取得一个更大的值-,但它之前已经被一个小的值占用了-然后我就直接把队列换成了个优先队列,按剩余时间的大小从大到下向下扩展状态,这样就可以保证bfs进行的时候,一定是按时间来一层一层扩展的,并且可以保证在从当前状态开始扩展之前,当前的状态一定是最优的。另外还有一个小坑-不知道是我别的地方写毁了还是怎么回事-..每次跳转空间或者是走到新的顶点时,如果目标点的dp值需要更新,显然需要根据更新后的值来扩展买,卖,不买不卖三种新的状态,但是如果目标点的值不需要更新,我依然需要按这个“不是目标状态最优的值”来扩展买,卖,不买不卖三种状态。举个例子 当前状态如果是2 2 0 25 下一步可以到达 2 2 1 24 然后卖掉一包盐扩展出 2 1 1 24,因为已经卖了一包盐了,他不可以再扩展出2 0 1 24.然后到达2 1 0 25的时候,下一步到达2 1 1 24发现这么走到2 1 1 24没有它当前的钱多,但这个不是最优的状态却可以继续扩展出2 0 1 24这个状态的最优值,所以在这就算得到的不是最优的钱数,我们依然需要往下扩展一下...然后就AC了......


      

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
using namespace std;
typedef long long ll;
bool vis[105][6][6][202];
int g[105][6][6][202];
int n,m,b,r,k,t,numtt;
int trade[105][6];
inline int getint() {
    char c = getchar();
    int t = 0;
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') {
        t = t * 10 + c - '0';
        c = getchar();
    }
    return t;
}
struct Edge
{
    int v,wt,wm,next;
}edge[202];
int ge[105];
struct sta
{
    int id,b,k,t;
    sta(){};
    sta(int x1,int x2,int x3,int x4)
    {
        id=x1;
        b=x2;
        k=x3;
        t=x4;
    }
//    bool operator>(const sta& s1)const
//    {
//
//        return t>s1.t;
//    }

    bool operator<(const sta& s1)const
    {
        return t<s1.t;
    }
};
int en;

void bfs()
{
    memset(vis,false,sizeof vis);
    memset(g,-1,sizeof g);
    priority_queue<sta> q;
    vis[1][0][0][t]=true;
    g[1][0][0][t]=r;
    q.push(sta(1,0,0,t));
    while(!q.empty())
    {
        sta now=q.top();
        sta tmp=now;
        q.pop();

//        vis[now.id][now.b][now.k][now.t]=false;
        int tid=now.id,tb=now.b,tk=now.k,tt=now.t;
        int fee;
        if (tt>0 && tid!=n && tid!=1)
        {
            tk++;
            if (tk==k) tk=0;
            tt--;
            if (g[tid][tb][tk][tt]<g[now.id][now.b][now.k][now.t])
            {
                g[tid][tb][tk][tt]=g[now.id][now.b][now.k][now.t];
                if (!vis[tid][tb][tk][tt])
                {
                    q.push(sta(tid,tb,tk,tt));
                    vis[tid][tb][tk][tt]=true;
                }
            }
                int ttk=tk,ttid=tid,ttb=tb,ttt=tt;
                fee=g[now.id][now.b][now.k][now.t];

                if (fee>=trade[ttid][ttk] && ttb<b)
                {
                    fee-=trade[ttid][ttk];
                    ttb++;
                    if (g[ttid][ttb][ttk][ttt]<fee)
                    {
                        g[ttid][ttb][ttk][ttt]=fee;
                        if (!vis[ttid][ttb][ttk][ttt])
                        {
                            q.push(sta(ttid,ttb,ttk,ttt));
                            vis[ttid][ttb][ttk][ttt]=true;
                        }
                    }
                }
                ttk=tk; ttid=tid; ttb=tb; ttt=tt;
                fee=g[now.id][now.b][now.k][now.t];
                if (ttb>0)
                {
                    fee+=trade[ttid][ttk];
                    ttb--;
                    if (g[ttid][ttb][ttk][ttt]<fee)
                    {
                        g[ttid][ttb][ttk][ttt]=fee;
                        if (!vis[ttid][ttb][ttk][ttt])
                        {
                            q.push(sta(ttid,ttb,ttk,ttt));
                            vis[ttid][ttb][ttk][ttt]=true;
                        }
                    }
                }


        }
        for (int j=ge[now.id]; j!=-1; j=edge[j].next)
        {
            tid=now.id;
            tb=now.b;
            tk=now.k;
            tt=now.t;
            fee=g[tid][tb][tk][tt];
            int u=now.id;
            int v;
            if (fee>=edge[j].wm && tt>=edge[j].wt)
            {
                v=edge[j].v;
                if ((v==1 || v==n) && tk!=0) continue;

                fee-=edge[j].wm;
                tt-=edge[j].wt;

                if (g[v][tb][tk][tt]<fee)
                {
                    g[v][tb][tk][tt]=fee;
                    if (!vis[v][tb][tk][tt] && v!=n)
                    {
                        q.push(sta(v,tb,tk,tt));
                        vis[v][tb][tk][tt]=true;
                    }
                }
                    if (v!=n && v!=1)
                    {
                        int ttk=tk,ttid=v,ttb=tb,ttt=tt;
                        fee=g[now.id][now.b][now.k][now.t]-edge[j].wm;
                        if (fee>=trade[v][tk] && ttb<b)
                        {
                            fee-=trade[v][tk];
                            ttb++;
                            if (g[ttid][ttb][ttk][ttt]<fee)
                            {
                                g[ttid][ttb][ttk][ttt]=fee;
                                if (!vis[ttid][ttb][ttk][ttt])
                                {
                                    q.push(sta(ttid,ttb,ttk,ttt));
                                    vis[ttid][ttb][ttk][ttt]=true;
                                }
                            }
                        }

                        ttb=tb;
                        fee=g[now.id][now.b][now.k][now.t]-edge[j].wm;

                        if (ttb>0)
                        {
                            fee+=trade[v][tk];
                            ttb--;
                            if (g[v][ttb][ttk][ttt]<fee)
                            {
                                g[v][ttb][ttk][ttt]=fee;
                                if (!vis[v][ttb][ttk][ttt])
                                {
                                    q.push(sta(v,ttb,ttk,ttt));
                                    vis[v][ttb][ttk][ttt]=true;
                                }
                            }
                        }

                    }

            }
        }
    }

}
int main()
{
//    freopen("in.txt","r",stdin);

//    scanf("%d",&numtt);
    numtt=getint();
    for (int ii=1; ii<=numtt; ii++)
    {
        memset(ge,-1,sizeof ge);
//        scanf("%d%d%d%d%d%d",&n,&m,&b,&k,&r,&t);
        n=getint(); m=getint();b=getint(); k=getint(); r=getint(); t=getint();

        for (int i=0; i<k; i++)
         for (int j=1; j<=n; j++)
//         scanf("%d",&trade[j][i]);
            trade[j][i]=getint();

        int x,y,z1,z2;
        en=0;
        for (int i=1; i<=m; i++)
        {
//            scanf("%d%d%d%d",&x,&y,&z1,&z2);
            x=getint(); y=getint(); z1=getint(); z2=getint();
            edge[en].v=y;
            edge[en].wt=z1;
            edge[en].wm=z2;
            edge[en].next=ge[x];
            ge[x]=en;
            en++;

        }
        bfs();
        int ans=-1;
       printf("Case #%d: ",ii);
        for (int i=0; i<=t; i++)
         for (int j=0; j<=b; j++)
         ans=max(ans,g[n][j][0][i]);
        if (ans>=0) printf("%d\n",ans);
        else puts("Forever Alone");

    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值