HDU 4784 Dinner Coming Soon(BFS+优先队列+状态转移)

分析:把时间作为优先队列的条件、然后bfs、

d[i][j][k][p]表示第i个城市、第j时刻、在第K维空间、有W包盐的最大价值

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
#define INF 0x7ffffff
const int N=105;
const int M=205;
int n,m,b,k,r,t;
//第i个城市、第j分钟、第K维空间、有P包盐的最大价值
int d[N][205][6][6];
bool vis[N][205][6][6];
int num[6][105];
int cnt;
struct edges
{
    int to,next,val,time;
}edge[M];
struct node
{
    int u,time,k,b;
    friend bool operator <(node a,node b)
    {
        return a.time>b.time;
    }
};
int head[N];
void init()
{
    cnt=0;
    memset(head,-1,sizeof(head));
}
int bfs()
{
    priority_queue<node>q;
    memset(vis,false,sizeof(vis));
    memset(d,0xff,sizeof(d));
    node now,tmp;
    now.b=0;
    now.u=1;
    now.k=0;
    now.time=0;
    d[1][0][0][0]=r;
    q.push(now);
    vis[1][0][0][0]=true;
    bool flag=false;
    while(!q.empty())
    {
        now=q.top();
        q.pop();
        if(now.time>t)break;
        if(now.u==n)continue;
        //到下一个城市
        for(int i=head[now.u];i!=-1;i=edge[i].next)
        {
            int w=edge[i].to;
            int f_cost=d[now.u][now.time][now.k][now.b]-edge[i].val;
            int f_time=now.time+edge[i].time;
            if(f_time>t||f_cost<0)continue;
            if(w==n&&now.k!=0)continue;
            if(w==n)flag=true;
            tmp.u=w;
            tmp.k=now.k;
            tmp.time=f_time;
            if(now.u!=1&&now.u!=n)
            {
                //买盐             如果在当前城市买了一袋盐且比以前的价值大
                if(now.b+1<=b&&f_cost-num[now.k][now.u]>d[w][f_time][now.k][now.b+1])
                {
                    d[w][f_time][now.k][now.b+1]=f_cost-num[now.k][now.u];
                    tmp.b=now.b+1;
                    if(!vis[tmp.u][tmp.time][tmp.k][tmp.b])
                    {
                        q.push(tmp);
                        vis[tmp.u][tmp.time][tmp.k][tmp.b]=true;
                    }
                }
                //卖盐
                if(now.b>0&&f_cost+num[now.k][now.u]>d[w][f_time][now.k][now.b-1])
                {
                    d[w][f_time][now.k][now.b-1]=f_cost+num[now.k][now.u];
                    tmp.b=now.b-1;
                    if(!vis[tmp.u][tmp.time][tmp.k][tmp.b])
                    {
                        q.push(tmp);
                        vis[tmp.u][tmp.time][tmp.k][tmp.b]=true;
                    }
                }
            }
            //不交易
            if(f_cost>d[w][f_time][now.k][now.b])
            {
                d[w][f_time][now.k][now.b]=f_cost;
                tmp.b=now.b;
                if(!vis[tmp.u][tmp.time][tmp.k][tmp.b])
                {
                    q.push(tmp);
                    vis[tmp.u][tmp.time][tmp.k][tmp.b]=true;
                }
            }
        }
        //穿越
        if(now.u!=1&&now.u!=n)
        {
            int f_cost=d[now.u][now.time][now.k][now.b];
            tmp.u=now.u;
            tmp.k=(now.k+1)%k;
            tmp.time=now.time+1;
            if(tmp.time>t)continue;

            //买盐
            if(now.b+1<=b&&f_cost-num[now.k][now.u]>d[now.u][tmp.time][tmp.k][now.b+1])
            {
                d[now.u][tmp.time][tmp.k][now.b+1]=f_cost-num[now.k][now.u];
                tmp.b=now.b+1;
                if(!vis[tmp.u][tmp.time][tmp.k][tmp.b])
                {
                    q.push(tmp);
                    vis[tmp.u][tmp.time][tmp.k][tmp.b]=true;
                }
            }
            //卖盐
            if(now.b>0&&f_cost+num[now.k][now.u]>d[now.u][tmp.time][tmp.k][now.b-1])
            {
                d[now.u][tmp.time][tmp.k][now.b-1]=f_cost+num[now.k][now.u];
                tmp.b=now.b-1;
                if(!vis[tmp.u][tmp.time][tmp.k][tmp.b])
                {
                    q.push(tmp);
                    vis[tmp.u][tmp.time][tmp.k][tmp.b]=true;
                }
            }
            tmp.b=now.b;
            //不交易
            if(f_cost>d[now.u][tmp.time][tmp.k][tmp.b])
            {
                d[now.u][tmp.time][tmp.k][tmp.b]=f_cost;
                if(!vis[tmp.u][tmp.time][tmp.k][tmp.b])
                {
                    q.push(tmp);
                    vis[tmp.u][tmp.time][tmp.k][tmp.b]=true;
                }
            }
        }
    }
    if(!flag)return -1;
    int ans=0;
    for(int i=0;i<=t;i++)
    {
        for(int j=0;j<=b;j++)
        {
            ans=max(ans,d[n][i][0][j]);
        }
    }
    return ans;
}
void add(int x,int y,int val,int time)
{
    edge[cnt].to=y;
    edge[cnt].val=val;
    edge[cnt].time=time;
    edge[cnt].next=head[x];
    head[x]=cnt++;
}
int main()
{
    int T;
    int cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d%d%d",&n,&m,&b,&k,&r,&t);
        init();
        for(int i=0;i<k;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&num[i][j]);
            }
        }
        for(int i=1;i<=m;i++)
        {
            int x,y,time,val;
            scanf("%d%d%d%d",&x,&y,&time,&val);
            add(x,y,val,time);
        }
        int ans=bfs();
        printf("Case #%d: ",cas++);
        if(ans!=-1)
        {
            printf("%d\n",ans);
        }
        else
        {
            printf("Forever Alone\n");
        }
    }
    return 0;
}


你可能感兴趣的:(bfs)