資料型別-進位制轉換、整型實型儲存
Description
你玩過“拉燈”遊戲嗎?25盞燈排成一個5x5的方形。每一個燈都有一個開關,遊戲者可以改變它的狀態。每一步,遊戲者可以改變某一個燈的狀態。遊戲者改變一個燈的狀態會產生連鎖反應:和這個燈上下左右相鄰的燈也要相應地改變其狀態。
我們用數字“1”表示一盞開著的燈,用數字“0”表示關著的燈。下面這種狀態
10111
01101
10111
10000
11011
在改變了最左上角的燈的狀態後將變成:
01111
11101
10111
10000
11011
再改變它正中間的燈後狀態將變成:
01111
11001
11001
10100
11011
給定一些遊戲的初始狀態,編寫程式判斷遊戲者是否可能在6步以內使所有的燈都變亮。
Input Format
第一行有一個正整數n,代表資料中共有n個待解決的遊戲初始狀態。
以下若干行資料分為n組,每組資料有5行,每行5個字元。每組資料描述了一個遊戲的初始狀態。各組資料間用一個空行分隔。
對於30%的資料,n<=5;
對於100%的資料,n<=500。
Output Format
輸出資料一共有n行,每行有一個小於等於6的整數,它表示對於輸入資料中對應的遊戲狀態最少需要幾步才能使所有燈變亮。
對於某一個遊戲初始狀態,若6步以內無法使所有燈變亮,請輸出“-1”。
Sample Input
3 00111 01011 10001 11010 11100 11101 11101 11110 11111 11111 01111 11111 11111 11111 11111
Sample Output
3
2
-1
題解:
簡單瞭解題意以後,我們可以運用遞推的思想,要想把所有的格子全部點亮,其實我們只用確定第一行的燈的所有的情況,因為第一行確定以後,我們看第二行,若第一行的某個為零,則下一行的對應位置進行點
擊,改變第一行的零為一,以此類推,以第i行來改變第i+1的情況。當到第五行時,為了不改變第四行的情況,我們便不遍歷,只需將五個字元判斷是否都為1即可,否則跳出迴圈。
程式碼如下:
#include<bits/stdc++.h>
using namespace std;
int t;
char a[6][6],b[6][6];
int ans;
int nex[5][2]={{0,0},{0,1},{0,-1},{1,0},{-1,0}};
void check(int x,int y)
{
for(int i=0;i<5;i++)
{
int xx=x+nex[i][0];
int yy=y+nex[i][1];
if(xx>=0 && xx<5 && yy>=0 && yy<5)
{
a[xx][yy]^=1;
}
}
}
//十字轉換。
int main()
{
// freopen("input.in","r",stdin);
// freopen("output.out","w",stdout);
//這倆不用管
cin>>t;
while(t--)
{
for(int i=0;i<=4;i++)
scanf("%s",a[i]);
ans=123003;
for(int i=1;i<=32;i++)
{
memcpy(b,a,sizeof(b));//將a中的資料記錄下來
int num=0;//記錄答案
for(int j=0;j<5;j++)
if(i>>j&1)//翻轉情況
{
num++;
check(0,j);
}
for(int k=0;k<4;k++)//只需列舉四行
for(int l=0;l<5;l++)
{
if(a[k][l]=='0')
{
num++;
check(k+1,l);
}
}
int tot=0;//判斷是否出現了五次
for(int j=0;j<5;j++)
{
if(a[4][j]=='0')
break;
else tot++;
}
memcpy(a,b,sizeof(a));//恢復其原有狀態
if(tot!=5)
continue;
ans=min(ans,num);//求最小
}
if(ans>6)
cout<<"-1"<<endl;
else
cout<<ans<<endl;
}
return 0;
}
❀完結撒花❀