http://poj.org/problem?id=3279
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2459
两题都是翻转一个数,然后它的上下左右都跟着变化。
这种题目的做法是用DFS枚举出第一行的所有状态,当第一行的状态确定之后,那么下面的状态也唯一了。因为下一行总是依赖上一行。然后对于每种状态check后求值就可了。
POJ代码:
#include
#include
#include
#include
using namespace std;
const int N = 20;
const int INF = 0x3f3f3f3f;
int ismap[N][N];
int ans[N][N],n,m,now,res=INF;
int cnt[N][N];
int pre[N][N];
int change[N];
bool check(int k)
{
if(k==n+1)
{
for(int i=1;i<=m;i++)
{
if(pre[k-1][i]) return false;
}
return true;
}
for(int i=1;i<=m;i++)
{
if(pre[k-1][i])
{
cnt[k][i]++;
now++;
pre[k-1][i] = 0;
pre[k][i] = pre[k][i] ? 0 : 1 ;
if(i>1) pre[k][i-1] = pre[k][i-1] ? 0: 1;
if(i1] = pre[k][i+1] ? 0 : 1;
if(k+1<=n) pre[k+1][i] = pre[k+1][i] ? 0 : 1;
}
}
check(k+1);
}
void dfs(int num)
{
if(num==m+1)
{
for(int i=1;i<=m;i++)
{
if(!change[i]) continue;
now ++;
cnt[1][i] ++;
pre[1][i] = pre[1][i] ? 0 : 1;
if(n>=2) pre[2][i] = pre[2][i] ? 0: 1;
if(i>1) pre[1][i-1] = pre[1][i-1] ? 0 : 1;
if(i1][i+1] = pre[1][i+1] ? 0: 1;
}
if(check(2) && now < res)
{
memcpy(ans,cnt,sizeof(ans));
res = now;
}
now = 0;
memset(cnt,0,sizeof(cnt));
memcpy(pre,ismap,sizeof(pre));
return;
}
for(int ch = 0; ch<2 ; ch++)
{
if(!ch) dfs(num+1);
else
{
change[num] = 1;
dfs(num+1);
change[num] = 0;
}
}
return;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&ismap[i][j]),pre[i][j] = ismap[i][j];
now = 0;
res = INF;
memset(cnt,0,sizeof(cnt));
memset(change,false,sizeof(change));
dfs(1);
if(res==INF) printf("IMPOSSIBLE\n");
else
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) printf("%d%c",ans[i][j],j==m?'\n':' ');
}
return 0;
}
UVA代码:
#include
#include
#include
#include
using namespace std;
const int N = 20;
const int INF = 0x3f3f3f3f;
int party[N][N];
int num[N][N],n;
int tmp[N][N],now,ans;
bool change[N];
int sum(int i,int j)
{
int sum = 0;
if(i-1>=1) sum+=num[i-1][j];
if(i+1<=n) sum+=num[i+1][j];
if(j-1>=1) sum+=num[i][j-1];
if(j+1<=n) sum+=num[i][j+1];
return sum;
}
void update(int i,int j)
{
if(i-1>=1) tmp[i-1][j]++;
if(i+1<=n) tmp[i+1][j]++;
if(j-1>=1) tmp[i][j-1]++;
if(j+1<=n) tmp[i][j+1]++;
return;
}
bool check(int k)
{
if(k==n+1)
{
for(int i=1;i<=n;i++)
if(tmp[n][i]%2) return false;
return true;
}
for(int i=1;i<=n;i++)
{
if(tmp[k-1][i]%2)
{
if(num[k][i]) return false;
now ++;
update(k,i);
}
}
check(k+1);
}
void dfs(int x)
{
if(x==n+1)
{
for(int i=1;i<=n;i++)
{
if(!change[i]) continue;
now++;
update(1,i);
}
if(check(2)) ans = min(ans,now);
memcpy(tmp,party,sizeof(tmp));
now = 0;
return;
}
if(num[1][x]) dfs(x+1);
else
{
for(int ch = 0; ch<2; ch++)
{
if(!ch) dfs(x+1);
else{
change[x] = true;
dfs(x+1);
change[x] = false;
}
}
}
return;
}
int main()
{
int T;
scanf("%d",&T);
for(int cas = 1;cas<=T;cas++)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&num[i][j]);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) party[i][j] = sum(i,j);
memset(change,false,sizeof(change));
memcpy(tmp,party,sizeof(tmp));
now = 0;
ans = INF;
dfs(1);
if(ans ==INF) ans = -1;
printf("Case %d: %d\n",cas,ans);
}
return 0;
}