TC SRM683 Div1 250

大意是有一排石子,每一堆有a[i]个,目标状态每一堆有b[i]个,每一步可以从一堆中取出一个石子转移到相邻的一个,其中1和n也算相邻也即环形。问最少步数。

比赛的时候写了个按照步数贪心的做法,FST了,当时想的贪心是从1到n/2枚举步数,for每一个需要石子的堆i,从(i+d)%n与(i-d)%n中看是否可以转移。

比赛结束自己想到一个反例

1 0 1 0 0 

0 1 0 1 0

答案应当是2,但是我那个贪心结果会成3。

后来看了下别人做法,大致有2种,一种是最优解中会存在某些点,这些点不会有穿越他们的MOVE,所以可以枚举每个点作为开始,将环形转为线性。

答案是每个a与b的前缀和之差的和。

还有一种做法是做一个c[i]=a[i]-b[i]的数组,sort之后,取中位数作为target。答案是所有值与中位数之差的和。

下面贴第一种解法的代码

 1 class MoveStones
 2 {
 3 public:
 4     long long get(vector <int> a, vector <int> b)  {
 5         long long s1=0,s2=0;
 6         int n=a.size();
 7         for (int i=0;i<n;i++) {
 8             s1+=a[i];
 9             s2+=b[i];
10         }
11         if (s1!=s2) return -1;
12         long long ret=1LL<<62;
13         for (int i=0;i<n;i++) {
14             long long now=0,s=0;
15             for (int j=0;j<n;j++){
16                 s+=a[j]-b[j];
17                 now+=abs(s);
18             }
19             ret=min(ret,now);
20             rotate(a.begin(),a.begin()+1,a.end());
21             rotate(b.begin(),b.begin()+1,b.end());
22         }
23         return ret;
24     }
25 };
View Code
原文地址:https://www.cnblogs.com/micrari/p/5229344.html