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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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 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]=trade[ttid][ttk] && ttb0)
                {
                    fee+=trade[ttid][ttk];
                    ttb--;
                    if (g[ttid][ttb][ttk][ttt]=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]=trade[v][tk] && ttb0)
                        {
                            fee+=trade[v][tk];
                            ttb--;
                            if (g[v][ttb][ttk][ttt]=0) printf("%d\n",ans);
        else puts("Forever Alone");

    }
    return 0;
}


你可能感兴趣的:(BFS,DFS)