Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2069 Accepted Submission(s): 517
Special Judge
题目大意:有n个人围成一圈,每个人手上都有一定数量的糖果,相邻两个人可是给一个糖果,但是只能给一次,如x,y。x可以给y一个糖果,或者y可以给x一个糖果。也可以不操作,即都不给糖果。第一个人可以给第n个人一个糖果,或者第n个人给第一个人一个糖果,或不给。问是否可以通过给糖果这样的操作,让所有的人手中的糖果数量相同。如果可以,输出YES和需要多少次,同时输出路径。否则输出NO。
解题思路:枚举第一个人对第二个人的三种操作,然后看第二个人跟average的差值,如果是-1,那么第二个人从第三个人手中拿走一个糖果,如果是1,那么第二个人给第三个人一个糖果,如果为零,则不操作。依次遍历到n。因为第n个人跟第1个人是可以操作的,所以我在操作第n个的时候,把对第一个人的操作放在了n+1的位置,c[1]+=c[n+1]判断第一个人的结果是否为零,如果为零,这说明可以,否则不可以。
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn=1e5+200;
typedef long long INT;
int a[maxn] ,b[maxn] ,c[maxn];
int f[3]={0,1,-1};
int abs(int x){
return x>0? x: -x;
}
struct Oper{
int x,y;
}oper[maxn];
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
INT sum=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum+=a[i];
}
if(sum%n!=0){
printf("NO\n");continue;
}else{
if(n==1){ //1个的时候必然YES
printf("YES\n0\n");
continue;
}
if(n==2){ //特判两个的情况
if(a[1]-a[2]==2){
printf("YES\n1\n");
printf("1 2\n"); continue;
}else if(a[1]-a[2]==-2){
printf("YES\n1\n");
printf("2 1\n");continue;
}else if(a[1]==a[2]){
printf("YES\n");
printf("0\n");continue;
}
}
const int ave=sum/n;
int flag=0;
for(int i=1;i<=n;i++){
b[i]=a[i]-ave; //把跟平均数的差值放在b数组中
if(abs(b[i])>2){
printf("NO\n");
flag=1;
break;
}
}
if(flag)
continue;
int num;
b[n+1]=0;
for(int k=0;k<3;k++){
num=0; //num放错位置,wa了
for(int i=1;i<=n+1;i++){
c[i]=b[i];
}
if(f[k]==1){
oper[num].x=2;
oper[num++].y=1;
}else if(f[k]== -1){
oper[num].x=1;
oper[num++].y=2;
}
//每次对c数组操作
c[1]+=f[k];
if(abs(c[1])>1 ){
continue;
}
c[2]-=f[k];
if(abs(c[2])>1){
continue;
}
int mark=0;
for(int i=2;i<=n;i++){ //遍历2-->n
if(c[i]==1){
c[i]-=1;
c[i+1]+=1;
if(i<n){
oper[num].x=i;
oper[num++].y=i+1;
}else{
oper[num].x=n;
oper[num++].y=1;
}
}else if(c[i]==-1){
c[i]+=1;
c[i+1]-=1;
if(i<n){
oper[num].x=i+1;
oper[num++].y=i;
}else{
oper[num].x=1;
oper[num++].y=n;
}
}
else if(abs(c[i])>1){
mark=1;
break;
}
}
if(mark){
continue;
}
if(c[1]+c[n+1]!=0){
continue;
}else{
flag=1;
break;
}
}
if(flag){
printf("YES\n");
printf("%d\n",num);
for(int i=0;i<num;i++){
printf("%d %d\n",oper[i].x,oper[i].y);
}
}else{
printf("NO\n");
}
}
}
return 0;
}
HDU 5353—— Average——————【贪心+枚举】
原文:http://www.cnblogs.com/chengsheng/p/4720135.html