您的位置:首页 > 其它

Codeforces Round #142 (Div. 2) C. Shifts

2017-07-04 19:53 411 查看
Description

You are given a table consisting of n rows and m columns. Each cell of the table contains a number, 0 or 1. In one move we can choose some row of the table and cyclically shift its values either one cell to the left, or one cell to the right.

To cyclically shift a table row one cell to the right means to move the value of each cell, except for the last one, to the right neighboring cell, and to move the value of the last cell to the first cell. A cyclical shift of a row to the left is performed similarly, but in the other direction. For example, if we cyclically shift a row “00110” one cell to the right, we get a row “00011”, but if we shift a row “00110” one cell to the left, we get a row “01100”.

Determine the minimum number of moves needed to make some table column consist only of numbers 1.

Input

The first line contains two space-separated integers: n (1 ≤ n ≤ 100) — the number of rows in the table and m (1 ≤ m ≤ 104) — the number of columns in the table. Then n lines follow, each of them contains m characters “0” or “1”: the j-th character of the i-th line describes the contents of the cell in the i-th row and in the j-th column of the table.

It is guaranteed that the description of the table contains no other characters besides “0” and “1”.

Output

Print a single number: the minimum number of moves needed to get only numbers 1 in some column of the table. If this is impossible, print -1.

Sample Input

Input

3 6

101010

000100

100000

Output

3

Input

2 3

111

000

Output

-1

Hint

In the first sample one way to achieve the goal with the least number of moves is as follows: cyclically shift the second row to the right once, then shift the third row to the left twice. Then the table column before the last one will contain only 1s.

In the second sample one can’t shift the rows to get a column containing only 1s.

思路:

对于每列计算把每一行中与此列最近的1移到此列的距离之和,然后取得最小值。

那么问题来了,怎么找到这一行中当此列的最近的1呢?

当然最近的1必然出现在以此列为中心线的左边或者右边(当然也包括在中心线上的)。当中心线靠右,写后面没有1了,那么它右边的1就应该是此行中最左边的1(移动就是一个环),同样当中心线靠左,且其左边没有1了,那么此时应当纳入计算的就应该是此行中最右边的那个一。

我们就可以在最左边和最右边加上额外的两个1,这样计算机会相当方便。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
string a;
int sum[10009];
memset(sum,0,sizeof sum);
int ans=0x3f3f3f3f;
int tmp[10009];
int flag=0;
for(int i=0;i<n;i++)
{
cin>>a;
if(flag) continue;
int s=1;
for(int j=0;j<a.size();j++)
{
if(a[j]=='1')
tmp[s++]=j;
}
if(s==1)//此行中没有一
{
flag=1;
continue;
}
tmp[0]=tmp[s-1]-m;//在左边加上最右边的那个一
tmp[s]=tmp[1]+m;//在右边加上最左边的那个一
int ans=0,l,r;
for(int j=0;j<m;j++)
{
r=j-tmp[ans];
l=tmp[ans+1]-j;
if(l==0)//如果两个参考的1中,靠右的那个一就在线上,那么为了使得下一次可以继续用两个1将参考列夹在中间,那么应该是的ans++
ans++;
sum[j]+=min(l,r);
}
}
if(flag)puts("-1");
else
{
for(int i=0;i<m;i++)
ans=min(ans,sum[i]);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: