好长的一道差分约束啊 啊 啊!
题意:
德黑兰的一家每天24小时营业的超市,需要一批出纳员来满足它的需求。超市经理雇佣你来帮他解决一个问题————超市在每天的不同时段需要不同数目的出纳员(例如,午夜只需一小批,而下午则需要很多)来为顾客提供优质服务,他希望雇佣最少数目的纳员。
超市经历已经提供一天里每一小时需要出纳员的最少数量————R(0),R(1),…,R(23)。R(0)表示从午夜到凌晨1:00所需要出纳员的最少数目;R(1)表示凌晨1:00到2:00之间需要的;等等。每一天,这些数据都是相同的。有N人申请这项工作,每个申请者i在每天24小时当中,从一个特定的时刻开始连续工作恰好8小时。定义ti(0<=ti<=23)为上面提到的开始时刻,也就是说,如果第i个申请者被录用,他(或她)将从ti时刻开始连续工作8小时。
试着编写一个程序,输入R(i),i=0,…,23,以及ti,i=1,…,N,它们都是非负整数,计算为满足上述限制需要雇佣的最少出纳员数目、在每一时刻可以有比对应R(i)更多的出纳员在工作
输入描述:
输入文件的第1行为一个整数T,表示输入文件中测试数据的数目(至多20个)。每个测试数据第一行为24个整数,表示R(0),R(1),…,R(23),R(i)最大可以取到1000。接下来一行是一个整数N,表示申请者的数目,0<=N<=1000。接下来有N行,每行为一个整数ti,0<=ti<=23,测试数据之间没有空行。
输出描述:
对输入文件中的每个测试数据,输出占一行,为需要雇佣的出纳员的最少数目。如果某个测试数据没有解。则输出”No Solution”。
思路:
没有思路。。。。。。。
所以 看了题解
然后 列出不等式 5个
其中 need【i】 表示第i个小时 需要的人
x[i]表示 申请的人
所以 我们要 求 的 ans 其实是 s[i](从0到i时刻 需要的人) 中的s[24]
【【这里 po主 是 第几个小时 所以 从1开始的哦】】 这样的话s[0]=0十分好用了
那么 5个狮子是什么呢
1、s[i]-s[i-1]>=0
2. s[i]-s[i-1]<=have[i]–>s[i-1]-s[i]>=-have[i]
3. s[i]-s[i-8]>=need[i] (9<=i<=24) 【【这个狮子不理解? 其实s【i】表示的是 从0到i时刻 正在 工作的 人 也就是 每个小时开始工作的人a[i]+a[i-1]+a[i-2]++++a[i-7] 表示的是8个小时的工作时间吗 不就是s[i]-s[i-8]】】
4. s[i]-s[i+16]>=need[i]-s24 隔天啊
5.隐藏大boss s[24]-s[0]>=ans 好难想啊 不加会错 亲测/(ㄒoㄒ)/~~
中间 spfa最长路 写错了,顺手加深了一下 理解 挺好
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
//by mars_ch
int need[31];//至少需要的人数
int x[31];//申请的人数
int s[31];//x的前缀和
int n,tot,res;
int dis[31];
int inq[31];
int cnt[31];
struct data
{
int f,t,w;
int nxt;
}e[400005];
int first[10005];
void add(int a,int b,int c)
{
e[++tot].f=a;
e[tot].t=b;
e[tot].w=c;
e[tot].nxt=first[a];
first[a]=tot;
}
void build(int ans)
{
memset(first,-1,sizeof(first));
tot=0;
add(0,24,ans);
for(int i=1;i<=24;i++)
{
add(i-1,i,0); //约束条件 s[i]-s[i-1]]>=0
add(i,i-1,-x[i]); //s[i-1]-s[i]>=-have[i];
}
for(int i=9;i<=24;i++)
{
add(i-8,i,need[i]); //s[i]-s[i-8]>=need[i]
}
for(int i=1;i<=8;i++)
{
add(i+16,i,need[i]-ans); //s[i]-s[i+16]>=need[i]-ans;
}
}
bool spfa(int ans)
{
memset(inq,0,sizeof(inq));
memset(dis,-127,sizeof(dis));
memset(cnt,0,sizeof(cnt));
queue<int> q;
while(!q.empty()) q.pop();
q.push(0);
dis[0]=0;
inq[0]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=first[u];i!=-1;i=e[i].nxt)
{
int v=e[i].t;
if(dis[v]<dis[u]+e[i].w)
{
dis[v]=dis[u]+e[i].w;
if(!inq[v])
{
inq[v]=1;
q.push(v);
if(++cnt[v] > 24)
{
return false;
}
}
}
}
inq[u]=0;
}
if(dis[24]>=ans)
{
return true;
}
else return false;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
/***************init***********/
bool flag=false;
memset(first,-1,sizeof(first));
tot=0;
memset(x,0,sizeof(x));
/***********input*************/
for(int i=1;i<=24;i++)
{
scanf("%d",&need[i]);
}
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
x[a+1]++;
}
for(int i=0;i<=n;i++)
{
build(i);
if(spfa(i))
{
printf("%d\n",i);
flag=true;
}
if(flag) break;
}
if(!flag)
{
printf("No Solution\n");
}
}
}