POJ 1275 Cashier Employment

这是《算法艺术与信息学竞赛》306页的原题,只不过是英文版。

在黑书上用的是最长路的算法 ,实际上最短路和最长路差不多的。

以下是黑书上的描述:

POJ 1275 Cashier Employment_第1张图片

枚举sum,通过求最短路或最长路来求解,这是一种方法。

黑书中说的二分法是针对当s[-1]!=sum时,它与sum的关系来二分搜索的,这里就用代码描述了。

下面是我的代码,用的是最短路求解。黑书中的r数组和t数组代表意义一样,s数组代码中用的是dis数组。

以下是代码:

#include <stdio.h>
#include <queue>
using namespace std;
#define inf 0x7fffffff
struct node
{
    int to,w,next;
} edge[25*30];
int r[25],t[25],dis[25],head[25],cnt,c[25];
bool vis[25];
void init()
{
    cnt=0;
    for(int i=0; i<25; i++)
    {
        head[i]=-1;
        dis[i]=inf;
        vis[i]=false;
        c[i]=0;
    }
    dis[0]=0;
}
void add(int u,int v,int w)
{
    edge[cnt].to = v;
    edge[cnt].w = w;
    edge[cnt].next = head[u];
    head[u] = cnt;
    cnt++;
}
void build(int ans)
{
    init();
    add(0,24,-ans);
    for(int i = 1; i <= 24; ++i)
    {
        add(i - 1,i,0);
        add(i,i - 1,t[i]);
    }
    for(int i = 17; i <= 24; ++i)
    {
        add(i ,(i+8)%24,-r[(i+8)%24] + ans);
    }
    for(int i = 1; i <= 16; ++i)
    {
        add(i,i+8,-r[i+8]);
    }
}
bool spfa(int ans)
{
    queue <int>q;
    q.push(0);
    vis[0]=true;
    c[0]=1;
    while(!q.empty())
    {
        int p,t=q.front();
        q.pop();
        p=head[t];
        vis[t]=false;
        while(p!=-1)
        {
            if(dis[edge[p].to]>dis[t]+edge[p].w)
            {
                dis[edge[p].to]=dis[t]+edge[p].w;
                if(!vis[edge[p].to])
                {
                    vis[edge[p].to]=true;
                    q.push(edge[p].to);
                    c[edge[p].to]++;
                    if(c[edge[p].to] > 24)
                    {
                        return false;
                    }
                }
            }
            p=edge[p].next;
        }
    }
    if(dis[24]==-ans)
    {
        return true;
    }
    else
    {
        return false;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int i,j,n,a;
        bool flat=true;
        for(i=1; i<=24; i++)
        {
            scanf("%d",&r[i]);
            t[i]=0;
        }
        scanf("%d",&n);
        for(i=1; i<=n; i++)
        {
            scanf("%d",&a);
            t[a+1]++;
        }
        for(i=0; i<=n; i++)
        {
            build(i);
            if(spfa(i))
            {
                printf("%d\n",i);
                flat=false;
                break;
            }
        }
        if(flat)
        {
            printf("No Solution\n");
        }
    }
    return 0;
}



你可能感兴趣的:(poj,SPFA,刷题,差分约束系统)