您的位置:首页 > 其它

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比较大,所以运行的时候重复的情况比较严重,所以运行时间比较长。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐