如果发现广告等破坏行为,请尽量将条目恢复到较早的版本而不是把相应内容直接删除,谢谢合作。

URAL/1060

来自"NOCOW"

跳转到: 导航, 搜索

我的应该是看起来最舒服的吧

#include <cstdio>
#include <cstring>
 
int s[5][5],tmp[5][5],dir[5][2],a[5],ans,b[5];
char ch[5][5];
bool tt=false;
 
inline void Change(int x,int y){
	tmp[x][y]^=1;
	for (int i=1;i<=4;i++){
		int fx=x+dir[i][0],fy=y+dir[i][1];
		if (fx>0 && fx<=4 && fy>0 && fy<=4)
			tmp[fx][fy]^=1;
	}
}
 
void Search(int k){
	if (k>4){
		for (int i=1;i<=4;i++)
			memcpy(tmp,s,sizeof tmp);
		memcpy(a,b,sizeof a);
		int sum=0,j;
		for (int i=1;i<=4;i++){
			j=0;
			while (a[i]){
				j++;
				if (a[i]&1){
					sum++;
					Change(i,j);
				}
				a[i]/=2;
			}
		}
		for (int i=1;i<=4;i++)
		for (int j=1;j<=4;j++)
		if (tmp[i][j]!=tmp[1][1])	return;
		tt=true;
		if (sum<ans)	ans=sum;
		return;
	}
	for (int i=0;i<1<<4;i++){
		b[k]=i;
		Search(k+1);
	}
}
 
int main(){
	freopen("s.in","r",stdin);
	freopen("s.out","w",stdout);
 
	dir[1][0]=0,dir[2][0]=0,dir[3][0]=1,dir[4][0]=-1;
	dir[1][1]=1,dir[2][1]=-1,dir[3][1]=0,dir[4][1]=0;
 
	for (int i=1;i<=4;i++)
		scanf("%s",&ch[i]);
	for (int i=1;i<=4;i++)
	for (int j=1;j<=4;j++)
		s[i][j]=(ch[i][j-1]=='b');
 
	ans=2134000000;
	Search(1);
 
	if (tt)	printf("%d\n",ans);
	else	printf("Impossible\n");
 
	return 0;
}

暴搜AC,看了看下面的程序,还是我的最清楚易懂

#include<iostream>
using namespace std;
long s,m=99999999;
long a[5][5]={0},g[5][5]={0};
void deal(int x,int y,int i)
{
    if (i==1)
    {
        g[x][y]=abs(g[x][y]-1);
        g[x+1][y]=abs(g[x+1][y]-1);
        g[x-1][y]=abs(g[x-1][y]-1);
        g[x][y+1]=abs(g[x][y+1]-1);
        g[x][y-1]=abs(g[x][y-1]-1);
        ++s;
    }
}
bool judge()
{
    int i,j;
    bool b=true;
    for (i=1;i<=4;++i)
    for (j=1;j<=4;++j)
     if (g[i][j]!=0) b=false;
    if (b==true) return true;
    for (i=1;i<=4;++i)
    for (j=1;j<=4;++j)
     if (g[i][j]!=1) return false;
    return true;
}    
int main(void)
{
    long i,j;
    char c;
    for (i=1;i<=4;++i)
     for (j=1;j<=4;++j)
      {
          cin>>c;
          if (c=='b') a[i][j]=1;
          else        a[i][j]=0;
      }    
    long i1,i2,i3,i4,
         i5,i6,i7,i8,
         i9,i10,i11,i12,
         i13,i14,i15,i16;
    for (i1=0;i1<=1;i1++)
    for (i2=0;i2<=1;i2++)
    for (i3=0;i3<=1;i3++)
    for (i4=0;i4<=1;i4++)
    for (i5=0;i5<=1;i5++)
    for (i6=0;i6<=1;i6++)
    for (i7=0;i7<=1;i7++)
    for (i8=0;i8<=1;i8++)
    for (i9=0;i9<=1;i9++)
    for (i10=0;i10<=1;i10++)
    for (i11=0;i11<=1;i11++)
    for (i12=0;i12<=1;i12++)
    for (i13=0;i13<=1;i13++)
    for (i14=0;i14<=1;i14++)
    for (i15=0;i15<=1;i15++)
    for (i16=0;i16<=1;i16++)
     {
         s=0;
         for (i=1;i<=4;i++)
         for (j=1;j<=4;j++)
          g[i][j]=a[i][j];
         deal(1,1,i1);
         deal(1,2,i2);
         deal(1,3,i3);
         deal(1,4,i4);
         deal(2,1,i5);
         deal(2,2,i6);
         deal(2,3,i7);
         deal(2,4,i8);
         deal(3,1,i9);
         deal(3,2,i10);
         deal(3,3,i11);
         deal(3,4,i12);
         deal(4,1,i13);
         deal(4,2,i14);
         deal(4,3,i15);
         deal(4,4,i16);
         if ((judge()==true) && (s<m)) m=s;
     }    
     if (m==99999999) cout<<"Impossible"<<"\n";
     else cout<<m<<"\n";
     return 0;
}    
 
from chuchill



Solution From Xcheng

枚举第一行的状态(DFS),然后从第二行起根据上一行的情况确定是否PRESS。



Solution From yiyi

同一硬币硬币翻2次还原,只需确定16个硬币中哪些被选择翻过. 枚举,使用位运算,共65536种状态.棋盘也转为16位二进制数. 用时:0.031s; 内存:208KB 具体实现,见代码:

prograM u1060;
var
  c,i,k,t,ans,x:longint;
  s:string[7];
begin
  ans:=-1; c:=0;
  for i:=1 to 4 do
    begin
      readln(s);
      for k:=1 to 4 do
        if s[k]='b' then c:=c or (1<<(k+ans));
      inc(ans,4);
    end;
  if (c=0) or (c=$ffff) then begin write('0'); halt(0) end;
  ans:=17;
  for k:=1 to 1<<16-1 do
    begin
      t:=c;
      if (k and (1<<0))<>0 then
        begin
          t:=t xor 1<<0;
          t:=t xor 1<<1;
          t:=t xor 1<<4;
        end;
      if (k and (1<<1))<>0 then
        begin
          t:=t xor 1<<0;
          t:=t xor 1<<1;
          t:=t xor 1<<2;
          t:=t xor 1<<5;
        end;
      if (k and (1<<2))<>0 then
        begin
          t:=t xor 1<<1;
          t:=t xor 1<<2;
          t:=t xor 1<<3;
          t:=t xor 1<<6;
        end;
      if (k and (1<<3))<>0 then
        begin
          t:=t xor 1<<2;
          t:=t xor 1<<3;
          t:=t xor 1<<7;
        end;
      if (k and (1<<4))<>0 then
        begin
          t:=t xor 1<<0;
          t:=t xor 1<<4;
          t:=t xor 1<<5;
          t:=t xor 1<<8;
        end;
      if (k and (1<<5))<>0 then
        begin
          t:=t xor 1<<1;
          t:=t xor 1<<4;
          t:=t xor 1<<5;
          t:=t xor 1<<6;
          t:=t xor 1<<9;
        end;
      if (k and (1<<6))<>0 then
        begin
          t:=t xor 1<<2;
          t:=t xor 1<<5;
          t:=t xor 1<<6;
          t:=t xor 1<<7;
          t:=t xor 1<<10;
        end;
      if (k and (1<<7))<>0 then
        begin
          t:=t xor 1<<3;
          t:=t xor 1<<6;
          t:=t xor 1<<7;
          t:=t xor 1<<11;
        end;
      if (k and (1<<8))<>0 then
        begin
          t:=t xor 1<<4;
          t:=t xor 1<<8;
          t:=t xor 1<<9;
          t:=t xor 1<<12;
        end;
      if (k and (1<<9))<>0 then
        begin
          t:=t xor 1<<5;
          t:=t xor 1<<8;
          t:=t xor 1<<9;
          t:=t xor 1<<10;
          t:=t xor 1<<13;
        end;
      if (k and (1<<10))<>0 then
        begin
          t:=t xor 1<<6;
          t:=t xor 1<<9;
          t:=t xor 1<<10;
          t:=t xor 1<<11;
          t:=t xor 1<<14;
        end;
      if (k and (1<<11))<>0 then
        begin
          t:=t xor 1<<7;
          t:=t xor 1<<10;
          t:=t xor 1<<11;
          t:=t xor 1<<15;
        end;
      if (k and (1<<12))<>0 then
        begin
          t:=t xor 1<<8;
          t:=t xor 1<<12;
          t:=t xor 1<<13;
        end;
      if (k and (1<<13))<>0 then
        begin
          t:=t xor 1<<9;
          t:=t xor 1<<12;
          t:=t xor 1<<13;
          t:=t xor 1<<14;
        end;
      if (k and (1<<14))<>0 then
        begin
          t:=t xor 1<<10;
          t:=t xor 1<<13;
          t:=t xor 1<<14;
          t:=t xor 1<<15;
        end;
      if (k and (1<<15))<>0 then
        begin
          t:=t xor 1<<11;
          t:=t xor 1<<14;
          t:=t xor 1<<15;
        end;
      if (t=0) or (t=$ffff) then
        begin
          x:=k;
          x:=(x and $55555555) + ((x>>1) and $55555555);
          x:=(x and $33333333) + ((x>>2) and $33333333);
          x:=(x and $0f0f0f0f) + ((x>>4) and $0f0f0f0f);
          x:=(x and $00ff00ff) + ((x>>8) and $00ff00ff);
          x:=(x and $0000ffff) + ((x>>16) and $0000ffff);
          if x<ans then ans:=x
        end;
    end;
  if ans=17
    then writeln('Impossible')
    else writeln(ans)
end.

裸搜就可以过,代码没有楼上恐怖

program cao;
const
  maxn=4;
  dx:array[1..5] of longint=(0,0,1,0,-1);
  dy:array[1..5] of longint=(0,1,0,-1,0);
 
var
  map,can:array[0..maxn,0..maxn] of boolean;
  a,b,c,d,e,f,g,h,i,j,k,l,n,m,p,q,ans:longint;
  ch:char;
 
procedure init;
begin
  for i:=1 to maxn do
  begin
    for j:=1 to maxn do
    begin
      read(ch);
      map[i,j]:=ch=‘b’;
    end;
    readln;
  end;
  for i:=1 to maxn do
    for j:=1 to maxn do
      can[i,j]:=true;
end;
 
procedure search(x,y,depth,last:longint);
var
  i,j:longint;
begin
 // writeln(x,’ ‘,y);
  if depth>=ans then exit;
  if (last=0)or(last=16) then
  begin
    if depth<ans then ans:=depth;
    exit;
  end;
  inc(y);
  if y>maxn then
  begin
    y:=1;
    inc(x);
  end;
  if x>maxn then exit;
  search(x,y,depth,last);
  for i:=1 to 5 do
    if can[x+dx[i],y+dy[i]] then
    begin
      map[x+dx[i],y+dy[i]]:=not(map[x+dx[i],y+dy[i]]);
      if map[x+dx[i],y+dy[i]] then dec(last) else inc(last);
    end;
  search(x,y,depth+1,last);
  for i:=1 to 5 do
    if can[x+dx[i],y+dy[i]] then
    begin
      map[x+dx[i],y+dy[i]]:=not(map[x+dx[i],y+dy[i]]);
      if map[x+dx[i],y+dy[i]] then dec(last) else inc(last);
    end;
end;
 
procedure main;
begin
  m:=0;
  for i:=1 to maxn do
    for j:=1 to maxn do
      if map[i,j]=false then inc(m);
  ans:=maxlongint;
  search(1,0,0,m);
end;
 
procedure print;
begin
  if ans=maxlongint then writeln(‘Impossible’)
  else writeln(ans);
end;
 
begin
  init;
  main;
  print;
end.



ls的各位不觉得这题跟1042是一样的么? --Wecing 21:51 2010年4月20日 (CST)


Orz Wecing


暴强的程序(非原创)

program cyd;
  var
    v:array[0..65535]of boolean;
    q:array[0..65535]of word;
    l:array[0..65535]of byte;
    map:array[1..4,1..4]of boolean;
    front,rear,s:word;
    i,j,x,y:byte;
    c:char;
  procedure flip(x,y:byte);
    begin
      if (x>0) and (x<5) and (y>0) and (y<5) then
        map[x,y]:=not map[x,y];
    end;
  begin
    q[0]:=0;
    for i:=1 to 4 do
      begin
        for j:=1 to 4 do
          begin
            read(c);
            q[0]:=q[0]*2;
            if c='b' then inc(q[0]);
          end;
      readln;
    end;
    fillchar(v,sizeof(v),0);
    front:=0;
    rear:=0;
    v[q[0]]:=true;
    l[q[0]]:=0;
    repeat
      for i:=1 to 4 do
        for j:=1 to 4 do
          begin
            s:=q[front];
            for x:=4 downto 1 do
              for y:=4 downto 1 do
                begin
                  map[x,y]:=odd(s);
                  s:=s div 2;
                end;
            flip(i,j);
            flip(i-1,j);
            flip(i+1,j);
            flip(i,j-1);
            flip(i,j+1);
            s:=0;
            for x:=1 to 4 do
              for y:=1 to 4 do
                s:=s*2+ord(map[x,y]);
            if not v[s] then
              begin
                v[s]:=true;
                inc(rear);
                q[rear]:=s;
                l[s]:=l[q[front]]+1;
              end;
          end;
      inc(front);
    until (front>rear) or v[0] or v[65535];
    if front>rear then
      writeln('Impossible') else
    if v[0] then writeln(l[0]) else writeln(l[65535]);
  end.

我整成高斯消元了……

/*
PROB: URAL 1060
LANG: C++
AUTHOR: mato_no1
*/
#include <stdio.h>
#include <string.h>
#include <bitset>
#define re(i, l, r) for (int i=l; i<r; i++)
#define rre(i, r, l) for (int i=r; i>=l; i--)
using std::bitset;
const int n = 16, P[n] = {19, 39, 78, 140, 305, 626, 1252, 2248, 4880, 10016, 20032, 35968, 12544, 29184, 58368, 51200}, INF = 1000000000;
bool a[n], b[n][n + 1];
int res = INF;
void init(void)
{
     re(i, 0, n) {a[i] = getchar() == 'b'; if (i % 4 == 3) char ch = getchar();}
}
void swap(int i, int j)
{
     int t;
     re(k, i, n+1) {t = b[i][k]; b[i][k] = b[j][k]; b[j][k] = t;}
}
void xx2(int v, int sum)
{
     if (sum >= res) return;
     if (v < 0) {res = sum; return;}
     if (b[v][v]) {
        rre(i, v-1, 0) if (b[i][v]) b[i][n] ^= b[v][n];
        xx2(v - 1, sum + b[v][n]);
        rre(i, v-1, 0) if (b[i][v]) b[i][n] ^= b[v][n];
     } else {
        xx2(v - 1, sum);
        rre(i, v-1, 0) if (b[i][v]) b[i][n] ^= 1;
        xx2(v - 1, sum + 1);
        rre(i, v-1, 0) if (b[i][v]) b[i][n] ^= 1;
     }
}        
void xx1(void)
{
     re(i, 0, n-1) {
       if (!b[i][i]) {
          int x = -1; re(j, i+1, n) if (b[j][i]) {x = j; break;}
          if (x >= 0) swap(i, x); else continue;
       }
       re(j, i+1, n) if (b[j][i]) re(k, i, n+1) b[j][k] ^= b[i][k];
     }
     re(i, 0, n) {bool ff = false; re(j, 0, n) ff |= b[i][j]; if (!ff && b[i][n]) return;}
     xx2(n - 1, 0);
}
void xxx(void)
{
     memset(b, false, sizeof(b));
     re(i, 0, n) {bitset <32> x = P[i]; re(j, 0, n) b[i][j] = x[j]; b[i][n] = a[i];}
     xx1();
     re(i, 0, n) {bitset <32> x = P[i]; re(j, 0, n) b[i][j] = x[j]; b[i][n] = !a[i];}
     xx1();
}
int main(void)
{
    init();
    xxx();
    if (res == INF) puts("Impossible"); else printf("%d\n", res);
    return 0;
}
个人工具