Problem Description
The military parade will last for n days. There is a aerobatic flight shows everyday during the parade. On the ith day , Pi pilots are required. But the pilots are not willing to work continually without an extra salary for even two days , because they are extremely tired.
There are m Holiday formulations in this country. For each formulation j , that is: when a pilot works on a day , if you pay him Sj dollars he is willing to come back Tj days after that day.
For example , If a pilot work on the rth day , and Tj==1 then he will return to work on r+1th day
At the very beginning there are k pilots , but of course you can hire more pilots. However , training new pilots require P days and for each new pilot you need pay him Q dollars. (Which means you can only use new pilots on Pth day or later)
Now our great king needs you to plan all these things. There must be enough pilots everyday and the cost must be minimized. Please tell the king what is the lowest cost;
Input
The first line contains a number T(T≤5), the number of testcases.
For each testcase, the first line contains a number n(n≤200)
On the second line , there are n numbers Pi(1≤i≤n) indicating the number of pilots needed on that day
On the third line , 3 numbers , m(1≤m≤5),P,Q
On the following m lines , each line has two numbers: Si , Ti
all input data x satisfy x∈[0,200]
Output
For each testcase, print a single number. The minimum cost.
If there is no solution , just put No solution
Sample Input
1
5 10
1 3 5 10 6
1 3 5
2 2
Sample Output
48
中文:
问题描述
国王阅兵式会持续 nn 天,每天都有一场飞机表演,第 ii 天的飞行表演需要 P_iP
i
个飞行员。由于每个飞行员都不愿意无偿的连续工作(哪怕连续工作 2 天 , 因为他们实在太困了),这个国家出台了 mm 个休假办法,当某个飞行员当天工作后,如果支付他 S_jS
j
的酬劳,他会在上次工作 T_jT
j
天后重新回来工作 (1\le j\le m)(1≤j≤m)。(多么好的制度)
如果飞行员在第 rr 天工作且此时 T_j = 1T
j
=1,那么他会就在 r+1r+1 天继续工作。
一开始有 kk 名飞行员,但当然还可以招募新的飞行员,但是,招募需要 PP 天的时间,并且招募来的每个飞行员需要支付 QQ 作为酬劳。(也就意味着到第 PP 天你才可能用到新招募来的飞行员)
现在国王把安排飞行表演的任务交给了你,你需要合理的安排这次飞行表演使得每天的飞行员都是充足的,并且让总费用最低。最后请输出总费用。
输入描述
第一行一个整数表示测试组数:T(T\le 5)T(T≤5)
对于每组数据,第一行两个整数 n (n\le 200)n(n≤200),kk 表示阅兵式的天数和一开始的飞行员数量。
第二行 nn 个数,用空格分隔,表示每一天所需要的飞行员的数目。
第三行 3 个整数 m(m \le 5),P, Qm(m≤5),P,Q, 具体意义参见题面。
接下来的 mm 行每行 2 个整数,即 S_i, T_iS
i
,T
i
。
输入的所有数据均在区间 [0 , 200][0,200] 内
输出描述
对每组数据输出一行表示答案 , 即最小费用。
如果无解输出 No solution
注: 整个过程不会超出32位带符号整数
输入样例
1
5 10
1 3 5 10 6
1 3 5
2 2
输出样例
48
官方题解,说的很清楚了,
代码:
(这次代码写的很清晰,应该很好懂~当然主要是要学会建图的思想)
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <queue>
#define oo 0x13131313
using namespace std;
const int MAXN=405;
const int MAXM=400010;
const int INF=0x3f3f3f3f;
struct Edge
{
int to,next,cap,flow,cost;
void get(int a,int b,int c,int d)
{
to=a,cap=b,cost=c;next=d;flow=0;
}
}edge[MAXM];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
int N;
void init(int n)
{
N=n;
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,int cost)
{
edge[tol].get(v,cap,cost,head[u]);head[u]=tol++;
edge[tol].get(u,0,-cost,head[v]);head[v]=tol++;
}
bool spfa(int s,int t)
{
queue<int>q;
for(int i=0;i<=N;i++)
{
dis[i]=INF;
vis[i]=false;
pre[i]=-1;
}
dis[s]=0;
vis[s]=true;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=false;
for(int i= head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&
dis[v]>dis[u]+edge[i].cost )
{
dis[v]=dis[u]+edge[i].cost;
pre[v]=i;
if(!vis[v])
{
vis[v]=true;
q.push(v);
}
}
}
}
if(pre[t]==-1) return false;
else return true;
}
int minCostMaxflow(int s,int t,int &cost)
{
int flow=0;
cost = 0;
while(spfa(s,t))
{
int Min=INF;
for(int i=pre[t];i!=-1;i=pre[edge[i^1].to])
{
if(Min >edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
}
for(int i=pre[t];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
cost+=edge[i].cost*Min;
}
flow+=Min;
}
return flow;
}
int n,k;
int p[402];
int s[402],t[402];
int m,P,q;
void input()
{
int sum=0;
int ans=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&p[i]);
sum+=p[i];
}
scanf("%d%d%d",&m,&P,&q);
int st=0,sd=n*2+1;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&s[i],&t[i]);
for(int j=1;j<=n;j++)
{
if(j+n+t[i]<=n*2)
addedge(j,j+n+t[i],INF,s[i]);
}
}
for(int i=1;i<=n;i++)
{
addedge(st,i,p[i],0);
}
for(int i=n+1;i<=2*n;i++)
{
addedge(i,sd,p[i-n],0);
}
addedge(st,n+1,k,0);
for(int i=P+n;i<=2*n;i++)
{
addedge(st,i,INF,q);
}
for(int i=1;i<n;i++)
{
addedge(i,i+1,INF,0);
addedge(i+n,i+n+1,INF,0);
}
if(minCostMaxflow(st,sd,ans)==sum)
cout<<ans<<endl;
else
cout<<"No solution"<<endl;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
init(MAXN);
input();
}
return 0;
}