描述
有一个正方形的墙,由N*N个正方形的砖组成,其中一些砖是白色的,另外一些砖是黄色的。Bob是个画家,想把全部的砖都涂成黄色。但他的画笔不好使。当他用画笔涂画第(i, j)个位置的砖时, 位置(i-1, j)、 (i+1, j)、 (i, j-1)、 (i, j+1)上的砖都会改变颜色。请你帮助Bob计算出最少需要涂画多少块砖,才能使所有砖的颜色都变成黄色。
输入第一行是一个整数n (1≤n ≤15),表示墙的大小。接下来的n行表示墙的初始状态。每一行包含n个字符。第i行的第j个字符表示位于位置(i,j)上的砖的颜色。“w”表示白砖,“y”表示黄砖。输出一行,如果Bob能够将所有的砖都涂成黄色,则输出最少需要涂画的砖数,否则输出“inf”。样例输入
5
wwwww
wwwww
wwwww
wwwww
wwwww
样例输出
15
来源1681
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 8 const int maxn = 20; 9 int wall[maxn][maxn], use[maxn][maxn]; 10 int n, minn = 9999, count0 = 0,flag=0; 11 12 void init() { 13 scanf("%d", &n); 14 for (int i = 1; i <= n; i++) 15 for (int j = 1; j <= n; j++) 16 { 17 char ch; 18 cin>>ch; 19 if (ch == 'w')wall[i][j] = 0; 20 else wall[i][j] = 1; 21 } 22 } 23 bool guess() { 24 for (int r = 1; r ) 25 for (int c = 1; c <= n; c++) { 26 use[r + 1][c] = (wall[r][c] + use[r][c] + use[r][c - 1] + use[r][c + 1] + use[r - 1][c]+1) % 2; 27 } 28 for (int c = 1; c <= n; c++) 29 if ((use[n][c - 1] + use[n][c + 1] + use[n-1][c]+use[n][c]) % 2 == wall[n][c]) 30 return false; 31 return true; 32 } 33 void solve() { 34 while (1) 35 { 36 if (guess()) { 37 for (int i = 1; i <= n; i++) 38 for (int j = 1; j <= n; j++) 39 { 40 if (use[i][j])count0++; 41 } 42 minn = min(count0, minn); 43 count0 = 0; 44 flag = 1; 45 } 46 for (int i = 2; i <= n; i++) 47 for (int j = 1; j <= n; j++) 48 use[i][j] = 0; 49 use[1][1]++; 50 int c = 1; 51 while (use[1][c] > 1) { 52 use[1][c] = 0; 53 use[1][++c]++; 54 } 55 if (c == n + 1)break; 56 } 57 } 58 59 int main() { 60 init(); 61 solve(); 62 if (flag) 63 printf("%d\n", minn); 64 else 65 printf("inf\n"); 66 return 0; 67 }
wa点:1)我居然把n写成了5
2)没有inf输出
3)step是+=,写成=真的是很神了
B:拨钟问题
描述
有9个时钟,排成一个3*3的矩阵。
|-------| |-------| |-------|
| | | | | | |
|---O | |---O | | O |
| | | | | |
|-------| |-------| |-------|
A B C
|-------| |-------| |-------|
| | | | | |
| O | | O | | O |
| | | | | | | | |
|-------| |-------| |-------|
D E F
|-------| |-------| |-------|
| | | | | |
| O | | O---| | O |
| | | | | | | |
|-------| |-------| |-------|
G H I
(图 1)
现在需要用最少的移动,将9个时钟的指针都拨到12点的位置。共允许有9种不同的移动。如下表所示,每个移动会将若干个时钟的指针沿顺时针方向拨动90度。
移动 影响的时钟
1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI
输入9个整数,表示各时钟指针的起始位置,相邻两个整数之间用单个空格隔开。其中,0=12点、1=3点、2=6点、3=9点。输出输出一个最短的移动序列,使得9个时钟的指针都指向12点。按照移动的序号从小到大输出结果。相邻两个整数之间用单个空格隔开。样例输入
3 3 0
2 2 2
2 1 2
样例输出
4 5 8 9
来源1166
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 using namespace std; 8 9 const int maxn = 30; 10 int clock0[10], use[10], res[maxn],state[10]; 11 int func[10][10], step = 0,minstep=9999; 12 13 void funset() { 14 for (int i = 1; i <= 9; i++) { 15 switch (i) 16 { 17 case 1:func[i][1] = 1, func[i][2] = 1, func[i][4] = 1, func[i][5] = 1; break; 18 case 2:func[i][1] = 1, func[i][2] = 1, func[i][3] = 1; break; 19 case 3:func[i][2] = 1, func[i][3] = 1, func[i][5] = 1, func[i][6] = 1; break; 20 case 4:func[i][1] = 1, func[i][4] = 1, func[i][7] = 1; break; 21 case 5:func[i][2] = 1, func[i][4] = 1, func[i][5] = 1, func[i][6] = 1, func[i][8]=1; break; 22 case 6:func[i][3] = 1, func[i][6] = 1, func[i][9] = 1; break; 23 case 7:func[i][4] = 1, func[i][5] = 1, func[i][7] = 1, func[i][8] = 1; break; 24 case 8:func[i][7] = 1, func[i][8] = 1, func[i][9] = 1; break; 25 case 9:func[i][5] = 1, func[i][6] = 1, func[i][8] = 1, func[i][9] = 1; break; 26 } 27 } 28 } 29 void init() { 30 for (int i = 1; i <= 9; i++) 31 { 32 int tmp; 33 scanf("%d", &tmp); 34 clock0[i] = (4 - tmp) % 4; 35 } 36 } 37 bool jud() { 38 for (int i = 4; i <= 9; i++) { 39 if(i<=7&&i>=4)use[i] = (444+clock0[i-3] - state[i-3]) % 4; 40 else if (i == 8)use[i] = (444+clock0[7] - state[7]) % 4; 41 else if (i == 9)use[i] = (444+clock0[5] - state[5]) % 4; 42 for (int j = 1; j <= 9; j++) { 43 state[j] += use[i] * func[i][j]; 44 } 45 } 46 for (int i = 1; i <= 9; i++) { 47 if (state[i] % 4 != clock0[i])return false; 48 } 49 step = 0; 50 for (int i = 1; i <= 9; i++) 51 step += use[i]; 52 return true; 53 } 54 void solve() { 55 for(int i=0;i<=3;i++) 56 for (int j = 0; j <= 3; j++) 57 for(int k=0;k<=3;k++) 58 { 59 use[1] = i, use[2] = j, use[3] = k; 60 for (int p = 1; p <= 3; p++) { 61 for (int o = 1; o <= 9; o++) { 62 state[o] += use[p] * func[p][o]; 63 } 64 } 65 if (jud() && step < minstep) { 66 minstep = step; 67 int c = 0; 68 for (int i = 1; i <= 9; i++) { 69 for (int j = 1; j <= use[i]; j++) 70 res[++c] = i; 71 } 72 break; 73 } 74 for (int p = 4; p <= 9; p++)use[p] = 0; 75 memset(state, 0, sizeof(int) * 10); 76 } 77 } 78 79 int main() { 80 funset(); 81 init(); 82 solve(); 83 printf("%d", res[1]); 84 for (int i = 2; res[i] != 0; i++)printf(" %d", res[i]); 85 printf("\n"); 86 return 0; 87 }
错误点:1)clock在g++编译中可能是某个内置变量,会CE
2)在 jud() 函数中,use的计算如果前面不事先+444之类的4的倍数,会出现负数,而且这个倍数还要稍微大一点
3)memset要加头文件
思路:依然是局部枚举,就是前3种方法如果定下来了,后面都能自己得出来
C:特殊密码锁
描述
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。
然而让人头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。
当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。
输入两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。输出至少需要进行的按按钮操作次数,如果无法实现转变,则输出impossible。样例输入
011
000
样例输出
1
1 #include2 #include 3 #include 4 #include 5 #include 6 #include <string> 7 #include 8 using namespace std; 9 10 const int maxn = 35; 11 int key[maxn], pwd[maxn], press[maxn], aft[maxn], leng, success = 0, step = 0, minstep = 9999;//press-whether to change the status;aft-status after the press 12 13 void init() { 14 string s1, s2; 15 cin >> s1 >> s2; 16 int l1 = s1.length(); 17 for (int i = 0; i < l1; i++) { 18 key[i + 1] = s1[i] - '0'; 19 pwd[i + 1] = s2[i] - '0'; 20 aft[i + 1] = s1[i] - '0'; 21 } 22 leng = l1; 23 } 24 void solve() { 25 for (int op = 0; op <= 1; op++) { 26 memset(press, 0, sizeof(int)*maxn); 27 step = 0; 28 press[1] = op; aft[1] ^= op; aft[2] ^= op; 29 step += op; 30 for (int i = 2; i <= leng; i++) { 31 if (aft[i - 1] != pwd[i - 1]) { 32 press[i] = 1; step++; 33 } 34 aft[i] ^= press[i]; 35 aft[i-1] ^= press[i]; 36 aft[i+1] ^= press[i]; 37 if (i == leng && aft[i] == pwd[i]) { 38 success = 1; 39 minstep = min(step, minstep); 40 } 41 } 42 for (int i = 1; i <= leng; i++)aft[i] = key[i]; 43 } 44 if (success)printf("%d\n", minstep); 45 else printf("impossible\n"); 46 } 47 48 int main() { 49 init(); 50 solve(); 51 return 0; 52 }
错误点:在 solve() 函数的循环中一定要把之前被改变的变量清零
思路:局部枚举 枚举第一个