Light
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 105 Accepted Submission(s): 42
Problem Description
Teacher Mai has a board of n rows and m columns. There is a light in each cell.
He can flip some lights: if this light is on, turn it off, else turn it on.
He can choose a cell(i,j), and he has following two operations:
1. Flip the light on the cells which share a common edge with cell(i,j).
2. Flip the light on the cells which share a common edge with cell(i,j) and cell(i,j).
You are given the initial state of board. Output the minimum operations to turn off the all the lights.
He can flip some lights: if this light is on, turn it off, else turn it on.
He can choose a cell(i,j), and he has following two operations:
1. Flip the light on the cells which share a common edge with cell(i,j).
2. Flip the light on the cells which share a common edge with cell(i,j) and cell(i,j).
You are given the initial state of board. Output the minimum operations to turn off the all the lights.
Input
There are multiple test cases, terminated by a line "0 0".
For each test case, the first line contains two integers n,m(1<=n,m<=10).
In following n lines, each line contains a string consisting of m characters, representing the initial state(0 means off, 1 means on).
For each test case, the first line contains two integers n,m(1<=n,m<=10).
In following n lines, each line contains a string consisting of m characters, representing the initial state(0 means off, 1 means on).
Output
For each case, output "Case #k: ans" first, where k is the case number counting from 1, ans is the minimum operations.
Sample Input
3 3 111 111 111 3 3 000 010 000 0 0
Sample Output
Case #1: 3 Case #2: 2
题意:一个地图有1,0符号,两种操作1.把一个点周围四个点取反,2,把一个点周围和自己取反,
问全部都是0至少几步操作
状态:0表示这个位置为0,没有操作过,1表示这个位置为0操作过1次,2表示这个位置为1没有操作过
因为操作偶数次周围四个点不变,奇数次周围四个点会改变
对于一个点,上方和左方操作次数确定后,可以确定这个点状态,这个点可以操作0,1,2次,
注意:确保每次上方的点都会变成0或1状态,如果i=0,这个点操作1次要忽略上方的状态,一个点操作两次,可以变成0或2的状态
#include<cstdio>
inline void min(int &x,int y){
x>y?x=y:0;
}
int len[15];
int dp[2][60000];
char word[11][11];
void init(){
len[0]=1;
for(int i = 1;i <= 14;i++)
len[i] = len[i-1]*3;
}
int nextstate(int v,int n,int i,int s){
if(i == 0) return s+n;
if(n==1) {
if(v == 0) v = 2;
else if(v == 2) v = 0;
}
return v*len[i-1]+n*len[i]+s;
}
int main(){
freopen("1005.in","r",stdin);
freopen("10051.out","w",stdout);
init();
int n,m,tt=1;
int i,j,k,u,v,no,s,s1,s2;
while(scanf("%d%d",&n,&m)!=EOF){
if(n==0&&m==0)return 0;
for( i = 0;i < n; i++){
getchar();
for(j=0;j<m;j++)
word[i][j]=getchar();
//scanf("%s",word[i]);
}
int p=0,q=1;
for( i=0;i<len[m];i++)dp[0][i]=1000000;
dp[0][0] = 0;
for( i = 0;i < n;i++){
for( j = 0;j < m;j++){
for(k=0;k<len[m];k++)dp[q][k]=1000000;
for(k=0;k<len[m];k++){
u = k/len[j]%3;
v = j==0?0:k/len[j-1]%3;
s2 = j==0?k-u*len[j]:k-u*len[j]-v*len[j-1];
no=word[i][j]-'0';
if((u+v)&1)no^=1;
if(u == 2){
s = nextstate(v,1,j,s2);
min(dp[q][s],dp[p][k]+1);
}
else if(u == 1){
if(no == 0){
s = nextstate(v,0,j,s2);
min(dp[q][s],dp[p][k]);
s = nextstate(v,1,j,s2);
min(dp[q][s],dp[p][k]+1);
}
else if(no == 1){
s = nextstate(v,2,j,s2);
min(dp[q][s],dp[p][k]);
s = s-2*len[j];
min(dp[q][s],dp[p][k]+2);
s = nextstate(v,1,j,s2);
min(dp[q][s],dp[p][k]+1);
}
}
else if(u == 0){
s = nextstate(v,0,j,s2);
if(no==0)min(dp[q][s],dp[p][k]);
min(dp[q][s],dp[p][k]+2);
s=s+2*len[j];
if(no==1)min(dp[q][s],dp[p][k]);
min(dp[q][s],dp[p][k]+2);
}
if(i==0) {
s1 = nextstate(v,1,j,s2);
min(dp[q][s1],dp[p][k]+1);
}
}
k=p,p=q,q=k;
}
}
int ans = 100000,flag;
for(i = 0;i < len[m];i++){
flag = 1;
for( j=0;j<m;j++)
if((i/len[j])%3==2)flag=0;
if(flag==1)min(ans,dp[p][i]);
}
printf("Case #%d: %d\n",tt++,ans);
}
return 0;
}