BOXES - Boxes
English | Vietnamese |
There are n boxes on the circle. The boxes are numbered from 1 to n (1<=n<=1000) in clock wise order. There are balls in the boxes, and the number of all the balls in the boxes is not greater than n.
The balls should be displaced in such a way that in each box there remains no more than one ball. In one move we can shift a ball from one box to one of it's neighboring boxes.
Write a program that: reads from the standard input the number of boxes n and the arrangement of balls in the boxes, computes the minimal number of moves necessary to displace the balls in such a way that in each box there remains no more than one ball, writes the result in the standard output.
Input
The first line of the input file contains an integer t representing the number of test cases (t<=20). Then t test cases follows. Each test case has the following form:
- The first line contains one positive integer n - the number of boxes
- The second line contains n nonnegative integer separated by single spaces. The i-th number is the number of balls in the i-th box.
Output
For each test case, output one nonnegative integer - the number of moves necessary to displace the balls in such a way that in each box there remains no more than one ball.
Example
Input: 1 12 0 0 2 4 3 1 0 0 0 0 0 1 Output: 19
【题目分析】
首先考虑,如果一个盒子里只有一个小球,显然是并不需要进行移动的,多余的话就需要移到只剩一个小球。如果为零,只能放进去一个小球。题目中的条件只允许向左右移动,那么我们加入这三组边
:(s,i,ai-1,0) (i,t,1,0) (i,j(与i相邻),正无穷,1)然后跑一边最小费用最大流就可以了。
【代码】
#include <cstdio> #include <cstring> #include <string> #include <queue> #include <iostream> using namespace std; const int inf =0x3f3f3f3f; const int maxn=10010; const int maxm=10010; #define M(a) memset(a,-1,sizeof a) #define M0(a) memset(a,0,sizeof a) #define MB(a) memset(a,0x3f,sizeof a) int n,m,S,T,ans,en=0; int v[maxn],u[maxn],cost[maxn],f[maxn],h[maxn],ne[maxn]; bool vis[maxm];//u->v int dis[maxm],with[maxm],minn[maxm]; inline void add(int a,int b,int r,int c) { u[en]=a;v[en]=b;ne[en]=h[a];f[en]=r;cost[en]=c; h[a]=en++; u[en]=b;v[en]=a;ne[en]=h[b];f[en]=0;cost[en]=-c;h[b]=en++; } inline bool tell() { queue<int>q; M0(vis);MB(dis);MB(minn);M0(with); q.push(S);vis[S]=true;dis[S]=0; while (!q.empty()) { int x=q.front();q.pop();vis[x]=false; for (int i=h[x];i!=-1;i=ne[i]) { int y=v[i]; if (dis[y]>dis[x]+cost[i]&&f[i]>0) { dis[y]=dis[x]+cost[i]; minn[y]=min(minn[x],f[i]); with[y]=i; if (!vis[y]) vis[y]=1,q.push(y); } } } if (dis[T]==0x3f3f3f3f) return false; return true; } int zeng() { for (int i=T;i!=S;i=v[with[i]^1]) { f[with[i]]-=minn[T]; f[with[i]^1]+=minn[T]; } return minn[T]*dis[T]; } inline void solve() { M(v);M(u);M(h);M(ne); int n; scanf("%d",&n); S=0;T=n+1,en=0;ans=0; for (int i=1;i<=n;++i){ int x; scanf("%d",&x); if (x) add(S,i,x-1,0); else add(i,T,1,0); if (i==1) add(i,n,inf,1),add(i,i+1,inf,1); else if (i==n) add(i,i-1,inf,1),add(i,1,inf,1); else add(i,i-1,inf,1),add(i,i+1,inf,1); } while (tell()) ans+=zeng(); printf("%d\n",ans); } int main() { int tt=0; scanf("%d",&tt); for (int z=1;z<=tt;++z) solve(); }