条形均分纸牌和环形均分纸牌问题


条形:P1031 [NOIP2002 提高组] 均分纸牌

※第一堆牌相差的牌只能由第二堆牌承担(给予或索要)

※第一堆牌都达到要求了又去动它干嘛

※可以直接删除第一堆牌

※第二堆牌神奇的变成了第一堆牌

※重复上述操作

※如果当前牌没操作就已经达标了跳过啊~

※下副牌变成负数又怎么样?

※ ∵ 上述步骤皆可逆

点击查看代码
#include
using namespace std;
int n,a[101],mid,all,ans;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]),all+=a[i];
	all/=n;
	for(int i=1;i<=n;i++)if(a[i]-all)
	a[i+1]+=a[i]-all,ans++;//如果是求传递纸牌的个数ans加abs(每组差值)就好
	printf("%d",ans);
	return 0;
}

环形:P2512 [HAOI2008]糖果传递

设Ai表示第i个小朋友原有的糖果数量,

ave表示所有小朋友糖果数量的平均数,

Xi表示第i个小朋友向左传的糖果数量。

根据初中知识 很明显这个点就是中位数

点击查看代码
#include
#define max(a,b) a>b?a:b
#define min(a,b) a

费用流做法:
P4016 负载平衡问题

这个题和糖果传递是一模一样的,学完网络流之后看到这个题目很典型的费用流

#include
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
#define inf 1e9
const int maxn=105;
int head[maxn],cnt=1;
int pre[maxn],last[maxn],vis[maxn],d[maxn],ff[maxn],s[maxn];
int n,S,T,mincost;
struct bian{
	int to,next,cost,flow;
}edg[maxn*maxn];
void add(int u,int v,int cost ,int flow){
	edg[++cnt].next=head[u];head[u]=cnt;edg[cnt].flow=flow;edg[cnt].cost=cost;edg[cnt].to=v;
	edg[++cnt].next=head[v];head[v]=cnt;edg[cnt].flow=0;edg[cnt].cost=-cost;edg[cnt].to=u;
}
queueQ;
bool spfa(){
	memset(vis,0,sizeof(vis));
	memset(d,0x7f,sizeof(d));
	memset(ff,0x7f,sizeof(ff));
	d[S]=0;vis[S]=1;Q.push(S);pre[T]=-1;
	while(!Q.empty()){
		int u=Q.front();
		Q.pop();vis[u]=0;
		for(int i=head[u];i;i=edg[i].next){
			int to=edg[i].to,flow=edg[i].flow,cost=edg[i].cost;
			if(flow&&d[to]>d[u]+cost){
				d[to]=d[u]+cost;
				pre[to]=u;
				last[to]=i;
				ff[to]=min(ff[u],flow);
				if(!vis[to]){
					vis[to]=1;
					Q.push(to);
				}
			}
		}
	}
	return pre[T]!=-1;
}
void calc(){
	while(spfa()){
		int now=T;
		mincost+=d[T]*ff[T];
		while(now!=S){
			edg[last[now]].flow-=ff[T];
			edg[last[now]^1].flow+=ff[T];
			now=pre[now];
		}
	}
}
int main(){
	cin>>n;
	S=0,T=n+1;
	int tot =0;
	for(int i = 1; i <= n; ++ i)
	{
		scanf("%d", &s[i]);
		tot += s[i];
		add(i, i < n ? i + 1 : 1, 1,inf);
		add(i, i > 1 ? i - 1 : n, 1,inf);
	}	
	tot /= n;
	for(int i = 1; i <= n; ++ i)
		if(s[i] > tot) add(S, i, 0,s[i] - tot);
		else if(s[i] < tot) add(i, T,0,tot - s[i]);
    calc();
    cout<