7-10 守卫棋盘 uva11214
输入要给n*m的棋盘 均小于10 某些格子有标记 用最少的皇后 辐射到所有的标记
限时 6666ms
用IDA* 时间6000 尴尬。
#include<bits/stdc++.h>
using namespace std;
#define N 10
int n,m;
int mp[N][N];
int cnt;
int visn[N];
int vism[N];
int visx[*N]; bool dfs(int d,int maxx)
{
if(cnt==)return true;
if(d==maxx)return false;
if( (maxx-d)*( *n+m- ) <cnt )return false;//毫无用处。。 int oldmap[N][N];//一定要开到里面 一开始开到外面错了!
memcpy(oldmap,mp,sizeof mp);
int oldcnt=cnt;
for(int i=;i<=n;i++)
if(!visn[i])
for(int j=;j<=m;j++)
if(!vism[j])
{
visn[i]=vism[j]=visx[i+j]=;
for(int k=;k<=n;k++)
if(mp[k][j])cnt--,mp[k][j]=;
for(int k=;k<=m;k++)
if(mp[i][k])cnt--,mp[i][k]=;
for(int k=;k<=n;k++)
for(int s=;s<=m;s++)
{
if( (s-k)==(j-i)||(s+k)==(i+j) )
if(mp[k][s]) mp[k][s]=,cnt--;
}
if(cnt!=oldcnt)
if(dfs(d+,maxx))return true;
memcpy(mp,oldmap,sizeof mp);
cnt=oldcnt;
visn[i]=vism[j]=;
}
return false;
} int solve()
{
if(cnt==)return ;
for(int maxx=;;maxx++){
memset(visn,,sizeof visn);
memset(vism,,sizeof vism);
if(dfs(,maxx) )return maxx;
}
} int main()
{
int cas=;
while(scanf("%d",&n),n)
{ cnt=;
scanf("%d",&m);getchar();
char ch;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
scanf("%c",&ch);
if(ch=='X')mp[i][j]=,cnt++;
}
getchar();
}
printf("Case %d: %d\n",++cas,solve());
}
}
每次dfs都要扫面落子的四个方位实在太费时间 真的铁脑残
应该像八皇后问题那样 设置标记数组就好了!! 900ms
#include<bits/stdc++.h>
using namespace std;
#define N 10
int n,m;
int mp[N][N];
int cnt;
int visn[N];
int vism[N];
int visx[*N];
int visy[*N]; bool judge()
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j]&&!visn[i]&&!vism[j]&&!visx[i+j]&&!visy[i-j+])return false; return true; } bool dfs(int d,int maxx)
{
if(judge())return true;
if(d==maxx)return false; for(int i=;i<=n;i++)
if(!visn[i])
for(int j=;j<=m;j++)
if(!vism[j])
{
visn[i]=vism[j]=;
int a=visx[i+j], b=visy[i-j+];
visx[i+j]=visy[i-j+]=; if(dfs(d+,maxx))return true;
visn[i]=vism[j]=;
visx[i+j]=a;visy[i-j+]=b;
}
return false;
} int solve()
{
if(cnt==)return ;
for(int maxx=;;maxx++){
memset(visn,,sizeof visn);
memset(vism,,sizeof vism);
memset(visx,,sizeof visx);
memset(visy,,sizeof visy);
if(dfs(,maxx) )return maxx;
}
} int main()
{
int cas=;
while(scanf("%d",&n),n)
{ cnt=;
scanf("%d",&m);getchar();
char ch;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
scanf("%c",&ch);
if(ch=='X')mp[i][j]=,cnt++;
else mp[i][j]=;
}
getchar();
}
printf("Case %d: %d\n",++cas,solve());
}
}
对行数进行优化 使行数升序:90ms 可以保证没有重复 !!! 上面那个代码有很多重复
#include<bits/stdc++.h>
using namespace std;
#define N 10
#define maxn 12
int n,m;
int mp[N][N];
int cnt;
int visn[N];
int vism[N];
int visx[*N];
int visy[*N];
int maxx;
bool judge()
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j]&&!visn[i]&&!vism[j]&&!visx[i+j]&&!visy[i-j+])return false;
return true;
} bool dfs(int d,int raw)
{
if(judge())return true;
if(d==maxx)return false; for(int i=raw;i<=n;i++)
for(int j=;j<=m;j++)
{
int c=visn[i],d1=vism[j],a=visx[i+j], b=visy[i-j+]; visx[i+j]=visy[i-j+]=visn[i]=vism[j]=; if(dfs(d+,i+))return true; visn[i]=c,vism[j]=d1;
visx[i+j]=a;visy[i-j+]=b;
}
return false;
} int solve()
{
for( maxx=;;maxx++){
memset(visn,,sizeof visn);
memset(vism,,sizeof vism);
memset(visx,,sizeof visx);
memset(visy,,sizeof visy);
if(dfs(,) )return maxx;
}
} int main()
{
int cas=;
while(scanf("%d",&n),n)
{
scanf("%d",&m);getchar();
char ch;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
scanf("%c",&ch);
if(ch=='X')mp[i][j]=;
else mp[i][j]=;
}
getchar();
}
printf("Case %d: %d\n",++cas,solve());
}
}
7-10 守卫棋盘 uva11214的更多相关文章
- UVA - 11214 Guarding the Chessboard(守卫棋盘)(迭代加深搜索)
题意:输入一个n*m棋盘(n,m<10),某些格子有标记.用最少的皇后守卫(即占据或者攻击)所有带标记的格子. 分析:因为不知道放几个皇后可以守卫所有带标记的格子,即回溯法求解时解答树的深度没有 ...
- UVA 11214 Guarding the Chessboard 守卫棋盘(迭代加深+剪枝)
暴力,和八皇后很像,用表示i+j和i-j标记主对角线,但是还是要加一些的剪枝的. 1.最裸的暴搜 6.420s,差点超时 2.之前位置放过的就没必要在放了,每次从上一次放的位置开始放 0.400s # ...
- UVA-11214 IDA*
利用迭代加深搜索,枚举需要的皇后数量,进行搜索. 对于10 * 10 的棋盘,最多需要5个皇后就能攻击整个棋盘,当0~4个皇后都不能搜索成功,那么5就不用搜索,直接打印. AC代码: #include ...
- [kuangbin带你飞]专题一 简单搜索 棋盘问题
题来:链接https://vjudge.net/problem/OpenJ_Bailian-132 J - 棋盘问题 1.题目: 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别. ...
- SGU 220.Little Bishops(DP)
题意: 给一个n*n(n<=10)的棋盘,放上k个主教(斜走),求能放置的种类总数. Solution: 一眼看上去感觉是状压DP,发现状态太多,没办法存下来... 下面是一个十分巧妙的处理: ...
- C语言数据结构----递归的应用(八皇后问题的具体流程)
本节主要讲八皇后问题的基本规则和递归回溯算法的实现以及具体的代码实现和代码分析. 转载请注明出处.http://write.blog.csdn.net/postedit/10813257 一.八皇后问 ...
- HTML页面过渡效果大全
IE要求: 在IE5.5及以上版本的浏览器中.启用网页过渡效果 默认情况下都已经启用了,如果需要手动启用则只需在Internet选项中: Advanced(高级) - Browsing(浏览) - E ...
- 界面编程之QT的文件操作20180729
/*******************************************************************************************/ 一.QT文件 ...
- [HAOI2015]数组游戏
题目大意: 有一排n个格子,每个格子上都有一个白子或黑子,在上面进行游戏,规则如下: 选择一个含白子的格子x,并选择一个数k,翻转x,2x,...,kx格子上的子. 不能操作者负. 思路: 将“某个格 ...
随机推荐
- [USACO09NOV]硬币的游戏A Coin Game
https://daniu.luogu.org/problemnew/show/P2964 dp[i][j] 表示桌面上还剩i枚硬币时,上一次取走了j个的最大得分 枚举这一次要拿k个,转移到dp[i- ...
- codevs 3369 膜拜(线型)
3369 膜拜 http://codevs.cn/problem/3369/ 题目描述 Description 神牛有很多…当然…每个同学都有自己衷心膜拜的神牛.某学校有两位神牛,神牛甲和神牛乙.新入 ...
- Swing教程
//用多线程刷新状态 new Thread(new Runnable(){ @Override public void run() { try { for(int i=0;i<1000;i++) ...
- 令assignment操作符返回一个reference to *this
[令assignment操作符返回一个reference to *this] 关于赋值,可以把它们写成连锁形式: int x, y, z; x =y =z =15; II赋值连锁形式 上述连锁赋值被解 ...
- Asp.net 中,在服务端向客户端写脚本的常用方法
在Asp.net 服务端处理脚本,一般都用 ClientScriptManager ,即web窗体服务端的this.ClientScript.该对象比较常用的方法: 1.RegisterArrayDe ...
- JS回调函数的应用,原来这么简单!
JS的回调函数很简单,看代码: 在a.js中 var myback = null; function load(obj){ myback = obj; } function save(){ // 后台 ...
- Android 动态添加线性布局(.java文件内) 实现控件按比例分割空间
这里实现 两个 编辑框同一水平上 按1:1分割空间 这里的1:1 比例可以通过 lp1.weight : 1p2.weight =m:n 实现 { LinearLayout l=new Linea ...
- 【转】C#使用PrintDocument打印 多页 打印预览
PrintDocument实例所有的订阅事件如下: 创建一个PrintDocument的实例.如下: System.Drawing.Printing.PrintDocument docToPrint ...
- 训练赛第二场G题 ZOJ 2343
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2343 解题报告:首先我假设最后的正确的结果是a[1] , a[2 ...
- sql server 查询本年的每个月的数据
一.以一行数据的形式,显示本年的12月的数据,本示例以2017年为例,根据CreateDate字段判断,计算总和,查询语句如下: end) as '1月', end) as '2月', end) as ...