/*
Annoying painting tool
http://acm.hdu.edu.cn/showproblem.php?pid=1801
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 321 Accepted Submission(s): 227
Problem Description
Maybe you wonder what an annoying painting tool is? First of all, the painting tool we speak of supports only black and white. Therefore, a picture consists of a rectangular area of pixels, which are either black or white. Second, there is only one operation how to change the colour of pixels:
Select a rectangular area of r rows and c columns of pixels, which is completely inside the picture. As a result of the operation, each pixel inside the selected rectangle changes its colour (from black to white, or from white to black).
Initially, all pixels are white. To create a picture, the operation described above can be applied several times. Can you paint a certain picture which you have in mind?
Input
The input contains several test cases. Each test case starts with one line containing four integers n, m, r and c. (1 ≤ r ≤ n ≤ 100, 1 ≤ c ≤ m ≤ 100), The following n lines each describe one row of pixels of the painting you want to create. The ith line consists of m characters describing the desired pixel values of the ith row in the finished painting ('0' indicates white, '1' indicates black).
The last test case is followed by a line containing four zeros.
Output
For each test case, print the minimum number of operations needed to create the painting, or -1 if it is impossible.
Sample Input
3 3 1 1
010
101
010
4 3 2 1
011
110
011
110
3 4 2 2
0110
0111
0000
0 0 0 0
Sample Output
4
6
-1
Source
HDOJ 2007 Summer Exercise(1)
*/
题目大意:
一个N×M的图片(N,M<100),每个点只有01两种状态。现在有一个R×C的画图工具(R<N,C<M),画一次能将矩形区域内的所有点状态翻转。初始时所有点都是0,现在给出一种目标图片,问最少需要几笔能画出来。
分析:
超级构造法
首先限制条件:
1、画笔在同一位置最多能画一次。(同一位置画两次<=>不画)。
2、考虑最左上角的一点,只有当画笔在最左上角的时候才能改变状态。
若该点和目标图片一致,则不用画;
否则需要在这个点的地方画一笔,同时将矩形其他点的状态翻转。
3、然后考虑左上角的第二个点,同样地,由于影响该点的画笔只有两个位置,而第一个位置刚才已经确定了,根据该点的状态也能确定是否要在第二个点画一笔……
4、依次确定从左上到右下的每一个点,
若该点与目标图片不一致,则必须在该点画一笔;否则不用。
*/
#include<cstdio>
#include<string.h>
#include<stdlib.h>
char num1[100][100];
bool num[100][100];
bool jude[100][100];
int main()
{
int n,m,r,c;
while(scanf("%d%d%d%d",&n,&m,&r,&c),(n||m||r||c))
{
getchar();
int i,j;
memset(num,0,sizeof(num));
for(i=0;i<n;i++) //若在此处直接用int数组或char数组单个输入num[i][j],结果是出不来的,试了一上午
{
scanf("%s",num1[i]);
for(j=0;j<m;j++)
if(num1[i][j]=='1')
num[i][j]=1;
else
num[i][j]=0;
}
memset(jude,0,sizeof(jude));
int count=0,p=0,q=0;
for(i=0;i<n-(r-1);i++)
for(j=0;j<m-(c-1);j++)
if(num[i][j]!=jude[i][j])
{
count++;
for(p=0;p<r;p++)
for(q=0;q<c;q++)
jude[p+i][q+j]=!jude[p+i][q+j];
}
int temp=1;
for(i=n-1;i>=0;i--)
for(j=m-1;j>=0;j--)
if(num[i][j]!=jude[i][j]&&temp)
temp=0;
if(temp)
printf("%d\n",count);
else
printf("-1\n");
}
return 0;
}