翻转快——搜索+贪心

http://poj.org/problem?id=3279

一般都玩过的游戏

翻转快,一块砖块翻开,其他周围四块跟它自己变的颜色相反

如果直接搜索的话,2^(15*15)铁定超时了

 

其实只要枚举2^15第一行,然后在此基础上贪心

即第一行为map[1][j]==1,下面也为 1

View Code
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cmath>
using namespace std;

int n,m,ret=0;
bool s[19];
bool map[19][19];
bool tmap[19][19];
bool hash[19][19];
bool r[19][19];

int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int add=0;
int i,j,k,ok=0;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
scanf("%d",&map[i][j]);
tmap[i][j]=map[i][j];
if(map[i][j]==1)
{
ok=1;
add++;
}
}
}

if(ok==0){
for(i=1;i<=n;i++){
printf("%d",map[i][1]);
for(j=2;j<=m;j++){
printf(" %d",map[i][j]);
}
printf("\n");
}
continue;
}

memset(hash,0,sizeof(hash));

int max=9999,count=0,dui,all=0;
int N=(int)pow(2*1.0,m*1.0);
for(k=0;k<N;k++)
{
memset(hash,0,sizeof(hash));
memset(s,0,sizeof(s));

count=0;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
map[i][j]=tmap[i][j];
}
}

j=m;
int temp=k;
while(temp){
if(temp%2==1){
s[j]=1;
}
temp=temp/2;
j--;
}

i=1;
for(j=1;j<=m;j++){
if(s[j]==1)
{
hash[i][j]=1;
count++;
map[i][j]=map[i][j]^1;
map[i][j+1]=map[i][j+1]^1;
map[i+1][j]=map[i+1][j]^1;
map[i][j-1]=map[i][j-1]^1;
}
}

for(i=1;i<n;i++){
for(j=1;j<=m;j++){
if(map[i][j]==1)
{
hash[i+1][j]=1;
count++;
map[i+1][j]=map[i+1][j]^1;
map[i][j]=map[i][j]^1;
map[i+1][j-1]=map[i+1][j-1]^1;
map[i+2][j]=map[i+2][j]^1;
map[i+1][j+1]=map[i+1][j+1]^1;
}
}
}

dui=0;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(map[i][j]==1)
{
dui=1;
break;
}
}
}

if(dui==0)
if(count<max)
{
all=1;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
r[i][j]=hash[i][j];
}
}
max=count;
}
}

if(all==0){
printf("IMPOSSIBLE\n");
continue;
}

for(i=1;i<=n;i++){
printf("%d",r[i][1]);
for(j=2;j<=m;j++){
printf(" %d",r[i][j]);
}
printf("\n");
}
}
return 0;
}



你可能感兴趣的:(搜索)