poj 1275 Cashier Employment

这篇博客介绍了如何解决POJ 1275问题,涉及单源最长路和单源最短路的转化方法。博主通过从小到大枚举答案来求解,并提到相关PDF资料已有详细解释。
摘要由CSDN通过智能技术生成

这里写图片描述


【分析】
这题比较难啊。。依然是求最少人数:单源最长路,我仍然转化为单源最短路来求。

这里写图片描述
这里写图片描述
嗯。。事实上我把 i加1 了,因为毕竟没有 f[-1]这玩意。。
首先将关系式转化为路径,然后从小到大枚举答案即可。
其实pdf里都讲清楚啦。。我在这貌似也只是打个酱油qwq


【代码】

//poj 1275 Cashier Employment
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define fo(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
vector <int> f[50],ff[50];
vector <int> l[50],ll[50];
int T,n,m,x,y,d,tmp,ans;
int dis[50],r[25],q[50001],t[25],huan[50];
bool vis[50];
inline void copy()
{
    fo(i,0,24)
    {
        ff[i].clear();
        ll[i].clear();
        x=f[i].size()-1;
        fo(j,0,x)
          ff[i].push_back(f[i][j]),ll[i].push_back(l[i][j]);
    }
}
inline bool spfa()
{
    memset(huan,0,sizeof huan);
    memset(dis,0x7f,sizeof dis);
    memset(vis,0,sizeof vis);
    dis[0]=0;
    vis[0]=1;
    huan[0]++;
    int h=0,tt=1;
    q[tt]=0;
    while(h<tt)
    {
        int u=q[++h];
        vis[u]=0;
        int x=ff[u].size()-1;
        fo(i,0,x)
        {
            int v=ff[u][i];
            if(dis[v]>dis[u]+ll[u][i])
            {
                dis[v]=dis[u]+ll[u][i];
                if(!vis[v])
                  vis[v]=1,q[++tt]=v,huan[v]++;
                if(huan[v]>25) return 0;
            }
        }
    }
    return 1;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        fo(i,0,49) f[i].clear(),l[i].clear();
        memset(t,0,sizeof t);
        memset(r,0,sizeof r);
        fo(i,0,49) dis[i]=1000000000;
        fo(i,1,24)
          scanf("%d",&r[i]);
        scanf("%d",&n);
        fo(i,1,n)
        {
            scanf("%d",&x);
            t[x+1]++;
        }
        fo(i,1,24)
          f[i-1].push_back(i),l[i-1].push_back(0);  //f[i]>=f[i-1]
        fo(i,8,24) 
          f[i-8].push_back(i),l[i-8].push_back(-r[i]);  //f[i]-f[i-8]>=r[i]
        fo(i,1,24)
          f[i].push_back(i-1),l[i].push_back(t[i]);  //f[i]-f[i-1]<=t[i]
        for(tmp=0;tmp<=n;tmp++)
        {
            copy();
            fo(i,1,7)
              ff[i+16].push_back(i),ll[i+16].push_back(tmp-r[i]);
            ff[0].push_back(24);
            ll[0].push_back(-tmp);
            if(spfa()) break;
        }
        if(tmp<=n) printf("%d\n",tmp);
        else printf("No Solution\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值