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.
属于查数问题
对于每一位置a[i][j],都要通过二分进行查找距离该点最近的1,移动到a[i][j]所需要的步数,因为最后一个可以通过右移,移到第一个位置,相当于围成一个圆圈,可以存三遍,取中间那一部分找。这个难就难在是没有排序的,不能确定1的位置,可以预处理一下,用一个数组存1的个数的前缀和这样就肯定是非递减的了,L函数是查左边最靠近该点的1的位置,用的是偏右查找,R函数是查右边最靠近该点的1的位置,用的是偏左查找。
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <stack>
#include <queue>
using namespace std;
#define mod 1e9+7
#define N 105
#define M 30005
#define inf 0x3f3f3f3f
typedef long long ll;
int b[N][M],c[N][M];
char a[N][M];
int n,m;
int L(int i,int j)
{
int l=1,r=j,mid;
while(l<r)
{
mid=(l+r)/2;
if(b[i][j]-b[i][mid]==0)
r=mid;
else
l=mid+1;
}
return j-r;
}
int R(int i,int j)
{
int l=j,r=3*m,mid;
while(l<r)
{
mid=(l+r)/2;
if(b[i][mid]-b[i][j]==0)
l=mid+1;
else
r=mid;
}
return l-j;
}
int main()
{
for(int i=1; i<=n; i++)
b[i][0]=0;
cin>>n>>m;
for(int i=1; i<=n; i++)
{
cin>>a[i]+1;
for(int j=1;j<=m;j++)
a[i][m+j]=a[i][2*m+j]=a[i][j];
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=3*m; j++)
{
if(a[i][j]=='1')
b[i][j]=b[i][j-1]+1;
else
b[i][j]=b[i][j-1];
}
if(b[i][3*m]==0)
{
cout<<-1;
return 0;
}
}
int f=m+1,ff=2*m;
for(int i=1; i<=n; i++)
{
for(int j=f; j<=ff; j++)
{
if(a[i][j]!='1')
c[i][j]=min(L(i,j),R(i,j));
else
c[i][j]=0;
}
}
int Min=inf,pp;
for(int j=f;j<=ff;j++)
{pp=0;
for(int i=1;i<=n;i++)
{
pp+=c[i][j];
}
Min=min(pp,Min);
}
cout<<Min;
}
Input
3 6
101010
000100
100000
Output
3
Input
2 3
111
000
Output
-1
Note
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.
给定一个包含0和1的表格,每次可以选择一行并将其值循环向左或向右移动一格,目标是找出达到某一列全为1所需的最小移动次数。如果无法实现,则输出-1。题目描述了输入输出格式,并提供了两个示例,一个是可行的情况,另一个是无法达成目标的情况。

237

被折叠的 条评论
为什么被折叠?



