C. Chef Monocarp
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Chef Monocarp has just put nn dishes into an oven. He knows that the ii-th dish has its optimal cooking time equal to titi minutes.
At any positive integer minute TT Monocarp can put no more than one dish out of the oven. If the ii-th dish is put out at some minute TT, then its unpleasant value is |T−ti||T−ti| — the absolute difference between TT and titi. Once the dish is out of the oven, it can't go back in.
Monocarp should put all the dishes out of the oven. What is the minimum total unpleasant value Monocarp can obtain?
Input
The first line contains a single integer qq (1≤q≤2001≤q≤200) — the number of testcases.
Then qq testcases follow.
The first line of the testcase contains a single integer nn (1≤n≤2001≤n≤200) — the number of dishes in the oven.
The second line of the testcase contains nn integers t1,t2,…,tnt1,t2,…,tn (1≤ti≤n1≤ti≤n) — the optimal cooking time for each dish.
The sum of nn over all qq testcases doesn't exceed 200200.
Output
Print a single integer for each testcase — the minimum total unpleasant value Monocarp can obtain when he puts out all the dishes out of the oven. Remember that Monocarp can only put the dishes out at positive integer minutes and no more than one dish at any minute.
Example
input
Copy
6 6 4 2 4 4 5 2 7 7 7 7 7 7 7 7 1 1 5 5 1 2 4 3 4 1 4 4 4 21 21 8 1 4 1 5 21 1 8 21 11 21 11 3 12 8 19 15 9 11 13
output
Copy
4 12 0 0 2 21
Note
In the first example Monocarp can put out the dishes at minutes 3,1,5,4,6,23,1,5,4,6,2. That way the total unpleasant value will be |4−3|+|2−1|+|4−5|+|4−4|+|6−5|+|2−2|=4|4−3|+|2−1|+|4−5|+|4−4|+|6−5|+|2−2|=4.
In the second example Monocarp can put out the dishes at minutes 4,5,6,7,8,9,104,5,6,7,8,9,10.
In the third example Monocarp can put out the dish at minute 11.
In the fourth example Monocarp can put out the dishes at minutes 5,1,2,4,35,1,2,4,3.
In the fifth example Monocarp can put out the dishes at minutes 1,3,4,51,3,4,5.
=========================================================================
很显然的套路就是对人建立n个点,然后对数轴 1--2n建立虚点,并拆开虚点,来保证每个时间点只能用一次,且虚点之间的花费应该是1,然后把每个人的a[i] 直接连接在数轴的虚点位置上,且花费为0,这样就把人引进了数轴里面,然后无论向左走还是向右走,都是花费的正值,合起来就是绝对值了
# include<iostream>
# include<cstring>
# include<queue>
using namespace std;
int n,m,st,ed,len=2;
typedef long long int ll;
typedef struct
{
int b,e;
ll flow,dis;
}xinxi;
xinxi s[101010];
int f[101010],nex[101010];
int pre[101010],vis[101010];
ll dis[101010],minn[101010];
ll mincost, maxflow;
queue<int>q;
void add(int x,int y,ll flow,ll dis)
{
s[len].b=x;
s[len].e=y;
s[len].flow=flow;
s[len].dis=dis;
nex[len]=f[x];
f[x]=len;
len++;
}
ll inf=1e18;
bool SPFA()
{
for(int i=1;i<=ed;i++)
{
vis[i]=0;
dis[i]=inf;
}
q.push(st);
minn[st]=inf;
dis[st]=0;
vis[st]=1;
while(!q.empty())
{
int now=q.front();
q.pop();
vis[now]=0;
int x=f[now];
while(x!=-1)
{
int j=s[x].e;
if(s[x].flow==0)
{
x=nex[x];
continue;
}
if(dis[j]>dis[now]+s[x].dis)
{
dis[j]=dis[now]+s[x].dis;
minn[j]=min(minn[now],s[x].flow);
pre[j]=x;
if(!vis[j])
{
vis[j]=1;
q.push(j);
}
}
x=nex[x];
}
}
return (dis[ed]!=inf);
}
void work()
{
maxflow=0;
mincost=0;
while(SPFA())
{
int x=ed;
maxflow+=minn[ed];
mincost+=minn[ed]*dis[ed];
int i;
while(x!=st)
{
i=pre[x];
s[i].flow-=minn[ed];
s[i^1].flow+=minn[ed];
x=s[i^1].e;
}
}
}
int a[210];
int main ()
{
int t;
cin>>t;
while(t--)
{
cin>>n;
len=2;
memset(f,-1,sizeof(f));
st=0;
ed=2*n+2*n+n+1;
for(int i=1;i<=n;i++)
{
cin>>a[i];
add(st,i,1,0);
add(i,st,0,0);
}
for(int i=n+1;i<=3*n;i++)
{
add(i,i+2*n,1,0);
add(i+2*n,i,0,0);
if(i==n+1)
{
add(i,i+1,inf,1);
add(i+1,i,0,-1);
}
else if(i==3*n)
{
add(i,i-1,inf,1);
add(i-1,i,0,-1);
}
else
{
add(i,i-1,inf,1);
add(i-1,i,0,-1);
add(i,i+1,inf,1);
add(i+1,i,0,-1);
}
add(i+2*n,ed,1,0);
add(ed,i+2*n,0,0);
}
for(int i=1;i<=n;i++)
{
int nowid=a[i]+n;
add(i,nowid,1,0);
add(nowid,i,0,0);
}
work();
cout<<mincost<<endl;
}
return 0;
}