问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

一道棋盘算法问题!用(c++)

发布网友 发布时间:2022-04-24 18:15

我来回答

2个回答

热心网友 时间:2023-10-31 02:07

真巧,pku 1753就是这题。。

前几天ICPC训练的时候还写过,现在懒得再写了,要用到bfs,我帮你找到了这题的解题报告,你看看吧:

解题思路:
BFS 即宽搜

因为这题说要找出最小值,也就是求最优值问题,那么,很快就可以想到DP 或者
搜索,而这题很难想出阶段以及状态,所以,构造DP的解法是比较困难的,至于
到底可不可以用DP,我也没有继续深思过,所以,我就想到直接搜索,把所有走法
都模拟出来,然后,哪种走法最快能够实现全盘为白或黑,则答案就出来了!
搜索有BFS和DFS两种,而BFS有能够求出最优值的特点,故考虑用BFS!

方法:
如果把走第i步之前,盘子上所有棋子构成的状态记为S(i-1),并且,初始状态
记为S(0)。而且,可以发现每走一步时,在棋盘上都有4*4=16中选择!但,当
如果盘子上出现的状态在之前也出现过,那么,就可以不用再继续走了!(即剪枝)

我们从第一步开始。。。
把走完第一步后盘子的所有状态都保存起来,如果用
很多个二维数组来保存这些状态就浪费空间了,并且,在之后的要寻找当前状态是否
已经出现过,也会出现麻烦!想一想,因为棋子是黑白两面,可以等价为“0”和“1”
两种性质,那么如果用一个一维数组保存起来的话,例如:

bwwb
bbwb
bwwb
bwww 1001110110011000
那么很快又可以发现另一个特点,图只有2^16个状态。

然后,开一个数组sign[65535]标记已经访问过的状态,则问题就迎刃而解了!

我的程序:

Problem: 1753 User: jlthero
Memory: 504K Time: 32MS
Language: C++ Result: Accepted

Source Code

#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
char piece[5][5];
int bina[16];
int sign[65536];
int ans;
int toint()
{
int value=0;
int i;
for(i=15;i>=0;i--)
{
value=value*2;
value+=bina[i];
}
return value;
}
void tochar(int n)
{
int i;
for(i=0;i<16;i++)
{
bina[i]=n%2;
n=n/2;
}
}
void slip(int i)
{
bina[i]=1-bina[i];
if(i%4!=0)
bina[i-1]=1-bina[i-1];
if(i%4!=3)
bina[i+1]=1-bina[i+1];
if(i-4>=0)
bina[i-4]=1-bina[i-4];
if(i+4<16)
bina[i+4]=1-bina[i+4];
}
int DFS()
{
vector<int>quene;
int i=0,j;
int value0,value1;
value0=toint();
if(value0==0||value0==65535)
return 0;
else if(sign[value0]==0)
{
quene.push_back(value0);
sign[value0]=1;
}
while(i<quene.size())
{
value0=quene[i];
tochar(value0);
for(j=0;j<16;j++)
{
slip(j);
value1=toint();
if(value1==0||value1==65535)
return sign[value0];
else if(sign[value1]==0)
{
quene.push_back(value1);
sign[value1]=sign[value0]+1;
}
slip(j);
}
i++;
}
return -1;
}
int main()
{
int i,j;
int t,ans;
while(scanf("%s %s %s %s",piece[0],piece[1],piece[2],piece[3])!=EOF)
{
for(i=0;i<4;i++)
{
t=i*4;
for(j=0;j<4;j++)
bina[t+j]=(piece[i][j]=='b'?1:0);
}
memset(sign,0,sizeof(sign));
ans=DFS();
if(ans==-1)
printf("Impossible\n");
else
printf("%d\n",ans);
}
return 0;
}

下面是王炽辉师兄的代码,代码长度要比我短很多^_^:

Problem: 1753 User: wangchi
Memory: 148K Time: 30MS
Language: C Result: Accepted

Source Code
#include<stdio.h>
#include<string.h>
#define MAX 1000000
int a[16], b[16], min;
char ch[4][5];

int legal()
{
int i, t, sum;
static int k = -1;
t = (a[0] + b[0] + b[1] + b[4]) % 2;
for(i = 1; i < 16; i++){
sum = a[i] + b[i];
if(i%4 != 0) sum += b[i-1];
if(i%4 != 3) sum += b[i+1];
if(i-4 >= 0) sum += b[i-4];
if(i+4 < 16) sum += b[i+4];
if(sum % 2 != t) return 0 ;
}
return 1;
}

void dfs(int i, int num)
{
if(i==16) {
if(min > num && legal()) min = num;
return;
}

b[i] = 0;
dfs(i+1, num);

b[i] = 1;
dfs(i+1, num+1);
}

int main()
{
int i, j, t;
while(scanf("%s%s%s%s", ch[0], ch[1], ch[2], ch[3]) != EOF){
for(i = 0; i < 4; i++){
t = i * 4;
for(j = 0; j < 4; j++)
a[t+j] = (ch[i][j]=='w')?0:1;
}

min = MAX;
dfs(0, 0);
if(min == MAX) printf("Impossible\n");
else printf("%d\n", min);
}
return 0;
}

热心网友 时间:2023-10-31 02:07

我想可以用递归或者堆栈实现吧,一个一个格的试下去,不行就出栈,应该能够穷举吧。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
如何批量导出全部微信好友微信号?快速导出微信联系人 交强险什么价格 命运冠位指定必练五星英灵是什么 命运冠位指定必练五星英灵推荐 自制豆沙馅能保存多久 红豆沙馅怎么保存 我高三,从现在到高考分数从350提到500多,有可能吗?我是文科生 高三350分还有5个月能提多少分 文科复读350多分可以提高多少 钱钟书-谈艺录-读本目录 送茶叶都有什么讲究呢? 中国文化送礼茶叶有什么讲究茶叶送礼有什么讲究和注意事项 关于介绍杨振宁的作文 美国公立高中申请都有什么条件 关于高考语文作文···学霸们请进 想象作文400字左右 杨振宁的作文 读美国高中十年级没初中毕业证可以申请吗 假期性国家大事件记事作文2016 想让儿子去美国读初中,需要什么要求条件? 申请美国高中都需要什么材料? 禁毒作文 罂粟花的自白 题目以及文章 急~!作文《三年后的我》怎么写 我的什么作文600字 出美国留学的条件 一张纸币为题的好处 人造卫星作文要形状自述功能名字300字 一角硬币自述 以百元钞票为题的话题作文 想问一下微信群名后面有个蓝色的圈是什么啊? ...有的好友头像右上角有蓝色小圈圈,是什么意思?并不是所有人都有。偶 ... 在微信小程序里的贝壳找房搜索的租房信息是否真实? 5*5棋盘问题C++ 关于欧拉回路的一题运用,看不懂题解,求解释 能用符号拼成柯南的样子吗 活动运营之后要做怎样的总结回顾 如何写活动总结 怎么写活动总结? 活动成果总结怎么写? 活动工作总结怎么写 活动总结怎么写?格式是怎样的,分几个部分来写? 活动评价万能模板是什么? 企业热线视频彩铃的月套餐包包括多少钱? 政企视频彩铃信息费是什么意思 视频彩铃单曲怎么收费? 出险后,意外保险报销要伤残鉴定吗? 自己摔倒了,骨折,有意外险,怎么申请伤残鉴定 意外险伤残签定到哪里做 意外险伤残鉴定怎么做 意外险伤残在哪鉴定 意外保险伤残鉴定部门 只上了意外险,能做伤残鉴定吗