题意:给一个4×4的矩阵,“+”表示该位置是锁这的,“-”表示该位置开着的,当改变某个位置的状态时,相应同行和同列的状态也改变,求最少的操作次数使全部16个位置开着,即所有位置是“-”状态。
解题思路:首先想到的是暴力:16个位置,每个位置有改变和不改变2种状态,共有2^16=65536种状态,用2进制或16层循环即可,然后看每种情况是否符合条件,最后找出操作次数最少的就行,中间的路径用数组保存下来。可惜啊,TLE...
还好,暴力能看出每种情况的路径,而且,暴力的结果绝对是对的!OK,根据暴力的结果找规律。
根据暴力的路径可以看出对于每个“+”只要把这个“+”所在行和列的所有点转换一下就行,有第三个样例可以看出,只要把重复的去掉就行!(因为转变2次相当于每操作,所以舍去),接下来就简单了,枚举每个“+”即可。
Memory: 344K Time: 63MS
#include <stdio.h>
#include <string.h>
using namespace std;
int b[6][6];//标记状态
void turn(int x,int y)//转换(x,y)点状态
{
for(int i=1;i<=4;i++)
{
if(b[x][i]==0) b[x][i]=1;
else b[x][i]=0;
if(b[i][y]==0) b[i][y]=1;
else b[i][y]=0;
}
if(b[x][y]==0) b[x][y]=1;
else b[x][y]=0;
}
int main()
{
char s[5][6];
// freopen("in.txt","r",stdin);
while(scanf("%s%s%s%s",s[1],s[2],s[3],s[4])!=EOF)
{
memset(b,0,sizeof(b));
for(int i=1;i<=4;i++)
{
for(int j=0;j<4;j++)
{
if(s[i][j]=='+')
{
turn(i,j+1);
}
}
}
int sum=0;//统计最后是"1"状态点
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
{
if(b[i][j]==1) sum++;
}
printf("%d\n",sum);
for(int i=1;i<=4;i++)//打印路径
for(int j=1;j<=4;j++)
{
if(b[i][j]==1)
{
printf("%d %d\n",i,j);
}
}
}
return 0;
}
附上暴力代码。。。
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
struct NODE
{
int x,y,nm;
}n[100][20];
int t[6][6];
void turn(int x,int y)
{
for(int i=1;i<=4;i++)
{
t[x][i]=-t[x][i];
t[i][y]=-t[i][y];
}
t[x][y]=-t[x][y];
}
int main()
{
char s[5][5];
int a[6][6],b[6][6];
// freopen("in.txt","r",stdin);
while(scanf("%s%s%s%s",s[1],s[2],s[3],s[4])!=EOF)
{
for(int i=1;i<=4;i++)
for(int j=0;j<4;j++)
{
if(s[i][j]=='+') a[i][j+1]=-1;
else a[i][j+1]=1;
}
memset(b,0,sizeof(b));
int ans=100000,k=1;
for(b[1][1]=0;b[1][1]<=1;b[1][1]++)//16层循环啊.....
for(b[1][2]=0;b[1][2]<=1;b[1][2]++)
for(b[1][3]=0;b[1][3]<=1;b[1][3]++)
for(b[1][4]=0;b[1][4]<=1;b[1][4]++)
for(b[2][1]=0;b[2][1]<=1;b[2][1]++)
for(b[2][2]=0;b[2][2]<=1;b[2][2]++)
for(b[2][3]=0;b[2][3]<=1;b[2][3]++)
for(b[2][4]=0;b[2][4]<=1;b[2][4]++)
for(b[3][1]=0;b[3][1]<=1;b[3][1]++)
for(b[3][2]=0;b[3][2]<=1;b[3][2]++)
for(b[3][3]=0;b[3][3]<=1;b[3][3]++)
for(b[3][4]=0;b[3][4]<=1;b[3][4]++)
for(b[4][1]=0;b[4][1]<=1;b[4][1]++)
for(b[4][2]=0;b[4][2]<=1;b[4][2]++)
for(b[4][3]=0;b[4][3]<=1;b[4][3]++)
for(b[4][4]=0;b[4][4]<=1;b[4][4]++)
{
int kk=1;
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
t[i][j]=a[i][j];
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
if(b[i][j]==1)
{
turn(i,j);
n[k][kk].x=i;
n[k][kk].y=j;
kk++;
}
}
}
kk--;
n[k][1].nm=kk;
int ok=1;
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
if(t[i][j]==-1){ok=0;break;}
}
}
if(ok)
{
ans=min(ans,kk);
k++;
}
}
printf("%d\n",ans);
for(int i=1;i<k;i++)
{
int m=n[i][1].nm;
if(m==ans)
{
for(int j=1;j<=m;j++)
{
printf("%d %d\n",n[i][j].x,n[i][j].y);
}
break;
}
}
}
return 0;
}