标签:i++ stdin 贪心 else 范围 道路 lan nbsp log
【题目描述】
P同学总共有k根火柴,分别放在摆成一列的n个火柴盒内,保证k是n的倍数。P同学想要每个火柴盒都有相同数目的火柴,每次他可以从一个火柴盒中拿一根火柴放到相邻的火柴盒中。他想知道他最少要移动多少次。
【输入格式】
从balance.in中读入。
第一行一个整数n,表示火柴盒数。
第二行n个整数,表示第i个火柴盒内有根火柴。
【输出格式】
输出到balance.out中。
一行一个整数,表示最少要移动多少次。
【样例一输入】
6
1 6 2 5 3 7
【样例一输出】
12
【子任务】
30%数据,1≤n≤100,0≤????≤100
100%数据,1≤n≤50000,0≤????≤10^9
模拟+贪心。
没有什么其他的特别的东西,类似于NOIP2002的纸牌。
我们可以先算出各盒火柴之和的sum,由p=sum/n可以得到每盒火柴的个数。
然后从1到n寻找,如果火柴数大于0,就把多出的火柴移到下一个火柴盒。
反之,如果小于0,就把下一个火柴盒的火柴移到这个火柴盒。
值得一提的是,即使火柴变成负数也可以实现,因为我们可以保证存在一种合适的移动方法恒为非负。
1 #include<cstdio>
2 #define MAXN 50005
3 #define LL long long
4 using namespace std;
5 int n,p=0;LL sum=0,cnt=0;
6 LL a[MAXN];
7 inline LL read(){
8 int x=0,f=1;char ch=getchar();
9 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
10 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
11 return x*f;
12 }
13 LL Abs(LL x){return x>0?x:-x;}
14 int main(){
15 freopen("balance.in","r",stdin);
16 freopen("balance.out","w",stdout);
17 n=read();
18 for(int i=1;i<=n;i++) a[i]=read(),sum+=a[i];
19 p=sum/n;
20 for(int i=1;i<=n;i++) a[i]-=p;
21 //for(int i=1;i<=n;i++) printf("a[i]=%d\n",a[i]);
22 for(int i=1;i<=n;i++) {
23 if(!a[i]) continue;
24 else if(a[i]<0) cnt-=a[i];
25 else if(a[i]>0) cnt+=a[i];
26 a[i+1]+=a[i];
27 }
28 printf("%lld",Abs(cnt));
29 return 0;
30 }
我们看见了一个由m行n列的1*1的格子组成的矩阵,每个格子(I,j)有对应的高度h[i][j]和初始的一个非负权值v[i][j].我们可以随便选择一个格子作为起点,然后在接下来的每一步当中,我们能且只能到达与当前格子有边相邻的四个格子中的高度不超过当前格子高度的格子,每当我们到达一个新格子(包括一开始选择的初始格子),我们就能得到该格子的权值分,然后该格子的权值就会等概率变成不比当前的权值大的一个非负权值。每一个格子在满足前面条件情况下,可以走任意多次。
我们希望得到一个最大的期望权值和路径,并给出这个最大的期望权值和。
输入格式:
第一行两个正整数表示m,n。
接下来的m行,每行n个正整数,表示h[i][j].
接下来的m行,每行n个非负整数,表示v[i][j].
输出格式:
一行一个实数,表示所求的最大期望权值和。保留零位小数。
输入样例:
1 3
1 2 1
1 2 3
输出样例:
5
数据范围:
对于30%的数据,保证n,m不超过100.
对于另外20%的数据,保证不存在相同的高度的格子。
对于100%的数据,保证n,m不超过1000.所有权值与高度不超过10^9.
留坑。下课填。
标签:i++ stdin 贪心 else 范围 道路 lan nbsp log
原文地址:http://www.cnblogs.com/drizzly/p/7622166.html