您的位置:首页 > 其它

codeforces 289B 递推

2015-12-22 01:57 316 查看
【题目链接】

http://codeforces.com/problemset/problem/289/B

【解题报告】

CF round 177 div2.

题目大意,给你一个N*M的矩阵,里面每个元素有一个val,你可以每次对它+d或者-d,问至少需要多少次操作,使得所有元素val相同。如果不可能,输出-1.

这道题做比赛的时候wa了五次。想对了一点,就是给定的n个数一定是模d的剩余相同。但是具体求最少操作的时候,我把元素值相同的点都合并了,然后误以为这其实是一个给定线段上N个点,求所有点到一个点的最小距离的一个题目,然后直接按照中间点是最优解的方法来做了。

但实际上,我没有考虑到,当某个点出现多次是,它的权重就会增加,那么它到别的点的代价就会增大,就不能单纯按线段上的点来考虑了。

所以这道题应当枚举每个点作为最终目标的时候,所需要的总操作数。

维护一个l[i]表示把第i个数左边的数变的都和它相同需要多少操作。

维护一个r[i]同理。

这可以在线性时间内得到。

之后扫一遍l[i]+r[i]即可。

应当说,因为比赛经验实在太少,所以面对构造算法模型的题目会想的很慢,而且极易想错或者忽略一些细节和边界条件。这几次比赛,包括去地大和北航的个人赛都只能过签到题,对稍微需要用点思维的题就会写崩,频频用很复杂的思维或者写很复杂的没必要的算法来想题做题,都体现了这一弱点。之后应当保持做个人赛的频率,提高比赛的感觉和构造能力的提高。

打得差不可怕,可怕的不能遭受挫折不愿正视缺点,妄自菲薄,妄自尊大。这样的道理很简单,却容易当局者迷。

忽然想到《灌篮高手》里,年轻的三井说:“教练,我想打篮球”,十分难过。只有年轻人才会执着于“梦想”,难以放弃的坚持才是对梦想的最重要的诠释。

所以把叹息留在身后,重新上路吧。

【参考代码】

#include<bits/stdc++.h>
using namespace std;

int N,M,d;
int a[10000+10];
int l[10000+10],r[10000+10];

int main()
{
cin>>N>>M>>d;
for(  int i=1; i<=N; i++ )
for(  int j=1; j<=M; j++ )
{
int t=(i-1)*M+j;
cin>>a[t];
}

sort(  a+1,a+1+N*M );
int temp=a[1];
for(  int i=1; i<=N*M; i++  )   //检查是否合法
{
a[i]-=temp;
if( a[i]%d  ){  cout<<-1<<endl; return 0;  }
}

for( int i=1; i<=N*M; i++ )
{
l[i]=l[i-1]+ (i-1)*(  a[i]-a[i-1]  )/d;
}
for( int i=N*M; i>=1; i--  )
{
r[i]=r[i+1]+ ( N*M-i )*(   a[i+1]-a[i] )/d;
}

int ans=1e9;
for( int i=1; i<=N*M; i++  )
{
ans=min(  ans, l[i]+r[i]  );
}
cout<<ans<<endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: