题意:一个01矩阵,每一行上的数字都可以向左向右移动(具体看题目描述),求最小的操作数,是矩阵某一列都是1.
做法:一开始,没看清题意,没有把从一侧推到另一侧的情况考虑进去...
#include <iostream>
#include <algorithm>
#include <cstdio>
#define eps 1e8
using namespace std;
int dp[102][10004],work[102][10004];
int main()
{
int n,m,pre,now,ans,first;
char x;
scanf("%d%d",&n,&m);
getchar();
for(int i=0;i<=n;i++)
{
fill(work[i],work[i]+m,eps);
fill(dp[i],dp[i]+m,eps);
}
for(int i=0;i<n;i++)
{
first=now=pre=-1;
for(int j=0;j<m;j++)
{
x=getchar();
x-='0';
if(x)
{
pre=now;
now=j;
if(first==-1)first=j;
work[i][j]=0;
for(int t=pre+1;t<now;t++)
{
if(pre!=-1)work[i][t]=t-pre;
work[i][t]=min(now-t,work[i][t]);
}
}
}
getchar();
if(now!=-1)
{
pre=now;
for(int t=pre+1;t<m;t++)
work[i][t]=t-pre;
}
if(first!=-1)
{
for(int t=pre+1;t<m;t++)
work[i][t]=min(work[i][t],first+m-t);
for(int t=0;t<first;t++)
work[i][t]=min(work[i][t],m-pre+t);
}
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(!i)dp[i][j]=work[i][j];
else if(dp[i-1][j]!=eps&&work[i][j]!=eps)dp[i][j]=dp[i-1][j]+work[i][j];
ans=eps;
for(int j=0;j<m;j++)ans=min(ans,dp[n-1][j]);
if(ans>=eps)printf("-1\n");
else printf("%d\n",ans);
return 0;
}