120战舰(9)144(10)165(12)179(15)195(18)208(21)
2016-11-08 18:25
627 查看
智力游戏
120战舰(9)规则和39战舰(3)82(6)一样,但是从6*6变成了10*10,比较复杂了。
我干脆写了一个程序来输出答案。
代码:
#include<iostream> using namespace std; ////////需要硬编码的3行/////////////// const int m4 = 2, m3 = 2, m2 = 3, m1 = 3; //战舰的个数,m4=2代表有2个长度为4的战舰 int line[nn] = { 2, 3, 2, 0, 5, 1, 0, 6, 2, 2 }; //列和 int row[nn] = { 1, 3, 1, 1, 4, 1, 5, 1, 2, 4 }; //行和 ////////需要硬编码的3行/////////////// const int nn = 10; //游戏的维度 int avail[nn][nn]; //能否放战舰,一个是战舰不相邻的问题,一个是游戏开始的障碍物问题 int out[nn][nn]; void save(int avail[nn][nn], int line[nn], int row[nn], int save_avail[nn][nn], int save_line[nn], int save_row[nn]) //保存3个数组 { for (int i = 0; i < nn; i++) { for (int j = 0; j < nn; j++)save_avail[i][j] = avail[i][j]; save_line[i] = line[i]; save_row[i] = row[i]; } } void re(int save_avail[nn][nn], int save_line[nn], int save_row[nn], int avail[nn][nn], int line[nn], int row[nn]) //还原3个数组 { for (int i = 0; i < nn; i++) { for (int j = 0; j < nn; j++)avail[i][j] = save_avail[i][j]; line[i] = save_line[i]; row[i] = save_row[i]; } } bool g(int n); bool f(int n, int l) //n是递归深度,也是放了多少个战舰,l是战舰长度 { for (int pr = 0; pr < nn; pr++) //横着放 { for (int pl = 0; pl + l <= nn; pl++) //(pr,pl)是战舰的最左那个格子 { bool f = false; for (int k = pl; k < pl + l; k++)if (avail[pr][k] == 0)f = true; if (f)continue; int save_avail[nn][nn]; //回溯的时候保存avail int save_line[nn]; int save_row[nn]; save(avail, line, row, save_avail, save_line, save_row); row[pr] -= l; if (row[pr] < 0) { re(save_avail, save_line, save_row, avail, line, row); //还原 continue; } f = false; for (int k = pl; k < pl + l; k++) { line[k]--; if (line[k] < 0)f = true; } if (f) { re(save_avail, save_line, save_row, avail, line, row); continue; } for (int i = pr - 1; i <= pr + 1; i++) { if (i < 0 || i >= nn)continue; for (int j = pl - 1; j <= pl + l; j++) { if (j<0 || j >= nn)continue; avail[i][j] = 0; } } if (g(n + 1)) { for (int k = pl; k < pl + l; k++)out[pr][k] = 1; return true; } else re(save_avail, save_line, save_row, avail, line, row); } } for (int pr = 0; pr + l <= nn; pr++) //竖着放 { for (int pl = 0; pl < nn; pl++) //(pr,pl)是战舰的最上那个格子 { bool f = false; for (int k = pr; k < pr + l; k++)if (avail[k][pl] == 0)f = true; if (f)continue; int save_avail[nn][nn]; //回溯的时候保存avail int save_line[nn]; int save_row[nn]; save(avail, line, row, save_avail, save_line, save_row); line[pl] -= l; if (line[pl] < 0) { re(save_avail, save_line, save_row, avail, line, row); continue; } f = false; for (int k = pr; k < pr + l; k++) { row[k]--; if (row[k] < 0)f = true; } if (f) { re(save_avail, save_line, save_row, avail, line, row); continue; } for (int i = pr - 1; i <= pr + l; i++) { if (i < 0 || i >= nn)continue; for (int j = pl - 1; j <= pl + 1; j++) { if (j<0 || j >= nn)continue; avail[i][j] = 0; } } if (g(n + 1)) { for (int k = pr; k < pr + l; k++)out[k][pl] = 1; return true; } else re(save_avail, save_line, save_row, avail, line, row); } } return false; } bool g(int n) //控制调用顺序 { if (n <= m4)return f(n, 4); else if (n <= m4 + m3)return f(n, 3); else if (n <= m4 + m3 + m2)return f(n, 2); else if (n <= m4 + m3 + m2 + m1)return f(n, 1); return true; } int main() { for (int i = 0; i < nn; i++) { for (int j = 0; j < nn; j++) { avail[i][j] = 1; //初始化,1表示可以放,0表示不可以 out[i][j] = 0; } } g(1); for (int i = 0; i < nn; i++) { for (int j = 0; j < nn; j++)cout << out[i][j] << " "; cout << endl; } cout << "end"; system("pause>nul"); return 0; }
在最前面有3行是需要硬编码的,其他地方就固定不变了。
144(10)
规则和上面的差不多,唯一的区别是,有些格子开始的时候就不能放战舰,那么只需要在main函数里面对avail数组进行初始化的时候把这些格子对应的初始化为0就可以了。
165(12)
179(15)
195(18)
208(21)
这一关因为m3和m2比较大,所以运行的时候重复的情况比较严重,所以运行时间比较长。
相关文章推荐
- 1,2,3,5,7,8,10,11,12,13,14,15,16,21,22 -》1~3,5,7~8,10~16,21~22
- /*请高手指点:C#中得到一串数字中有连续数字的开始和结束位置?比方说0,2,5,6,7,10,12,13,15,18……中,就有5,6,7和12,13两组连续(或更多),则要得到5,6,7的始末位置
- 现有杂乱无序的1-20二十个数,这二十个数为:1,18,4,13,6,10,15,2,17,3,19,7,16,8,11,14,9,12,5,20,试依次求出相邻四个数之和的最大和最小值
- |1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20所有这些字符串,把它的数字一个个剥离??
- 10 12 15 又演杯具
- 180中国跳棋(12)186(13)191(14)196(15)201(16)205(17)209.5(18)
- 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
- PowerDesigner 生成带注释SQL 各个版本通用10(12、15)
- leetcode 21:Merge Two Sorted Lists(15-10-9)
- NEERC 15 (10/12)
- 《C++捷径教程》读书笔记--Chapter 18--C++的I/O系统--12-15
- 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8
- 15*4+18*4+21*4+24*4+。。。+99*4=?这个用什么公式来算
- leetcode18:4Sum(15-10-6)
- 10 12 18 头晕
- 10 12 21 放松
- 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8
- text1.txt begin10 11 12 20 21 22 30 31 32 end text2.txt begin 15 16 17 25 26 27 35 36 37 得到text3.txt
- Daily Scrum - 12/15-21
- 启动2个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后再线程1打印11,12,13,14,15,直到打印到50