破坏正方形UVA1603
题目大意
有一个由火柴棍组成的边长为n的正方形网格,每条边有n根火柴,共2n(n+1)根火柴。从上至下,从左到右给每个火柴编号,现在拿走一些火柴,问在剩下的后拆当中ongoing,至少还要拿走多少根火柴才能破坏掉所有的正方形?

虽然本题的数据规模不大,但是却有多种选择火柴棍的方法,导致如果直接爆搜的话会炸,因此考虑采用IDA*算法。
首先来看,我们该如何存储这个火柴棍图?
个人比较喜欢把这样一个火柴棍图转化成这样的数组形式,存为square[][]
0 1 0 1 0 1 0
1 0 1 0 1 0 1
0 1 0 1 0 1 0
1 0 1 0 1 0 1
0 1 0 1 0 1 0
1 0 1 0 1 0 1
0 1 0 1 0 1 0
其中,0代表火柴棍交界的地方,1代表火柴棍。
先给所有火柴棍编上号。在a上遍历,按序命名,用一个map<pair<int,int>,int> name进行映射
之后,给每一个正方形编一个号,在用一个vector存一下每个正方形的所有边,便于进行搜索时快速确定本次该删除哪一条边。在存储边的同时,还要记录下当前这个正方形的原大小(即火柴棍全部摆满)和现在的大小(删除火柴棍后的数量),比较这两个的大小即可确定现在这个正方形是否被破坏。存储过程用函数实现
点击查看代码
void get(int x,int y,int len,int ccnt) {//搜正方形,并把组成正方形的每个火柴添加上当前的正方形
int tx = x,ty = y;
for(ty = y; ty <= 2 * n + 1; ty++){//向右走
if(cnt == len){cnt = 0;break;}
if(square[tx][ty]){
cnt++;
match[ccnt].push_back(name[make_pair(tx,ty)]);
}
}
for(tx = x; tx <= 2 * n + 1; tx++){//向下走
if(cnt == len){cnt = 0;break;}
if(square[tx][ty]){
cnt++;
match[ccnt].push_back(name[make_pair(tx,ty)]);
}
}
for(ty; ty >= 1; ty--){//向左走
if(cnt == len){cnt = 0;break;}
if(square[tx][ty]){
cnt++;
match[ccnt].push_back(name[make_pair(tx,ty)]);
}
}
for(tx; tx >= 1; tx--){
if(cnt == len){cnt = 0;break;}
if(square[tx][ty]){
cnt++;
match[ccnt].push_back(name[make_pair(tx,ty)]);
}
}
}
IDA*的关键就在于估价函数,这个题该如何来写估价函数呢?
理想状况下,破坏一个正方形,可以顺带把这个正方形周围的正方形全部破坏(这就是估价函数和搜索函数check函数不同的原因,tmp当然就是来记录最理想状况的),当然,只是理想状况。如果按照这种方式进行破坏也不能在规定时间内破坏完毕,那这样的方案一定不可行,直接剪枝。
搜索时,以没有被破坏的正方形为对象,遍历它的每一条边,然后挨个搜索即可
在实现当中,可以看见我们使用了memcpy这个函数,它可以将一个数组内的值复制到另一个数组里面,挺方便的
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 22;
int t,n;
bool square[MAXN][MAXN],use[MAXN * MAXN];//vis表示正方形i是否被破坏 ,use表示该火柴棍是否被使用
int cnt,now,del;
map<pair<int,int>,int> name;
bool found;
bool tmp[MAXN * MAXN];
vector<int> match[MAXN * MAXN];//编号i的正方形由哪些火柴棍组成
void get(int x,int y,int len,int ccnt) {//搜正方形,并把组成正方形的每个火柴添加上当前的正方形
int tx = x,ty = y;
for(ty = y; ty <= 2 * n + 1; ty++){//向右走
if(cnt == len){cnt = 0;break;}
if(square[tx][ty]){
cnt++;
match[ccnt].push_back(name[make_pair(tx,ty)]);
}
}
for(tx = x; tx <= 2 * n + 1; tx++){//向下走
if(cnt == len){cnt = 0;break;}
if(square[tx][ty]){
cnt++;
match[ccnt].push_back(name[make_pair(tx,ty)]);
}
}
for(ty; ty >= 1; ty--){//向左走
if(cnt == len){cnt = 0;break;}
if(square[tx][ty]){
cnt++;
match[ccnt].push_back(name[make_pair(tx,ty)]);
}
}
for(tx; tx >= 1; tx--){
if(cnt == len){cnt = 0;break;}
if(square[tx][ty]){
cnt++;
match[ccnt].push_back(name[make_pair(tx,ty)]);
}
}
}
bool _check(int i){
for(int j=0;j<match[i].size();++j){
if(use[match[i][j]])
return 0;
}
return 1;//没被破坏
}
bool check(int i){
for(int j=0;j<match[i].size();++j){
if(tmp[match[i][j]])
return 0;
}
return 1;
}
void init(){
name.clear();
for(int i = 1; i < MAXN*MAXN; i++)match[i].clear();
memset(square,0,sizeof square);
memset(use,0,sizeof use);
memset(tmp,0,sizeof tmp);
}
int estimate(){
int sum = 0;
memcpy(tmp,use,sizeof(use));
for(int i = 1; i <= now; i++){
if(check(i)){
sum++;
for(int j=0;j<match[i].size();++j)
tmp[match[i][j]]=1;
}
}
return sum;
}
void IDAstar(int x,int maxd){
if(x+estimate()>maxd)return;
for(int i=1;i<=now;++i){
if(_check(i)){
for(int j=0;j<match[i].size();++j){
use[match[i][j]]=1;
//v.push_back(id[i][j]);
IDAstar(x+1,maxd);
//v.pop_back();
use[match[i][j]]=0;
if(found)return;
}
return;
}
}
found=1;
return;
}
int main(){
cin >> t;
while(t--){
init();
cin >> n;
bool flag = 0;
cnt = now = 0;
for(int i = 1; i <= 2 * n + 1; i++){//构造正方形图并给火柴棍编号
if(i % 2 == 0)flag = 1;
for(int j = 1; j <= 2 * n + 1; j++){
square[i][j] = flag;
if(flag == 1){
cnt++;
name[make_pair(i,j)] = cnt;
}
flag = !flag;
}
}
cnt = 0;
for(int i = 1; i <= 2 * n + 1; i++){//寻找正方形
if(i % 2 == 0)continue;
for(int j = 1; j <= 2 * n + 1; j++){
if(!square[i][j])continue;
for(int len = 1; len <= n; len++){
if((i + 2 * (len - 1) + 1 > 2 * n + 1) || (j + 2 * (len - 1) + 1 > 2 * n + 1))break;
now++;
get(i,j,len,now);
}
}
}
cin >> del;
int a;
for(int i = 1; i <= del; i++){
cin >> a;
use[a] = 1;
}
for(int i = estimate();;i++){
found = 0;
IDAstar(0,i);
if(found){
cout << i << "\n";
break;
}
}
}
}
破坏正方形UVA1603的更多相关文章
- 7-15 Square Destroyer 破坏正方形 uva1603
先是处理所有的正方形 从边长为1开始 将其边存好 满边存好 然后不断扫描正方形 并且进行拆除 直到拆完或者 步数小于等于9(启发方程 因为n小于等于5 九次足以将所有的拆完) 代码实施有很多细 ...
- UVa 1603 破坏正方形
https://vjudge.net/problem/UVA-1603 题意:有一个火柴棍组成的正方形网格,计算至少要拿走多少根火柴才能破坏所有正方形. 思路:从边长为1的正方形开始遍历,将正方形的边 ...
- IDA*
模拟退火 基本思路(Main Thoughts): IDA*是一种优秀的搜索法,在一般的实际问题中,它比普通的搜索更快. 通过迭代加深和估价函数剪枝来搜索. 通常处理没有层数上界或上界很多大的搜索. ...
- [LeetCode] Matchsticks to Square 火柴棍组成正方形
Remember the story of Little Match Girl? By now, you know exactly what matchsticks the little match ...
- [LeetCode] Maximal Square 最大正方形
Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and ret ...
- 【纯css】左图右文列表,左图外框宽度占一定百分比的正方形,右上下固定,右中自动响应高度。支持不规则图片。
查看演示 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...
- Mint Linux 安装 DotnetCore 遭遇无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系
evlon@evlon-ThinkPad-T530 ~ $ apt install dotnet-dev-1.0.0-preview2-003121 正在读取软件包列表... 完成 正在分析软件包的依 ...
- BZOJ1047: [HAOI2007]理想的正方形 [单调队列]
1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2857 Solved: 1560[Submit][St ...
- [译]JavaScript源码转换:非破坏式与再生式
原文:http://ariya.ofilabs.com/2013/06/javascript-source-transformation-non-destructive-vs-regenerative ...
随机推荐
- vue - Vue脚手架
今天的内容vue脚手架,越来越有内味了,也慢慢地开始有点难度了哈哈,但是没有关系,慢慢学慢慢琢磨,我倒是感觉有点越来越像node了,不知道怎么回事,这是要向后端发展的节奏啊 一.初始化Vue脚手架 1 ...
- k8s系列--node(k8s节点介绍,新增节点,移除节点)
一.简介 Node是Pod真正运行的主机,可以是物理机也可以是虚拟机. Node本质上不是Kubernetes来创建的, Kubernetes只是管理Node上的资源. 为了管理Pod,每个Node节 ...
- 从标准输入流中读取并执行shell指定函数
巧妙的ohmytmux配置 看oh my tmux的配置,发现他们很巧妙的将配置和shell函数放到一个文件里 比如切换鼠标模式的相关配置和shell函数, # : << EOF # .. ...
- asp.net6 blazor 文件上传
微软在asp.net6中给blazor新增了一个IJSStreamReference的接口. 我们今天的所有内容,都要依赖这个接口,因为它可以把流直接传到c#中,这样我们就可以做很多的骚操作了. 今天 ...
- Date类的常见用法——JavaSE基础
Date类的常见用法 Date类属于java.util包 因此需要导入Date类 Date() 分配一个Date对象,并初始化此对象为系统当前的日期和时间,可以精确到毫秒). Date(long da ...
- keil的重复定义问题:Error: L6200E: Symbol F6x8 multiply defined
keil的重复定义问题:Error: L6200E: Symbol F6x8 multiply defined 在驱动oled和电容按键都遇到了,所以记录这个错误,以后再遇到也不至于手足无措 Keil ...
- go-zero 微服务实战系列(二、服务拆分)
微服务概述 微服务架构是一种架构风格,它将一个大的系统构建为多个微服务的集合,这些微服务是围绕业务功能构建的,服务关注单一的业务功能,这些服务具有以下特点: 高度可维护和可测试 松散的耦合 可独立部署 ...
- 2021.04.24【NOIP提高B组】模拟 总结
2021.04.24[NOIP提高B组]模拟 总结 T1 题意:有一圈数.两两之间有加法或乘法操作, 问你开始断掉那条边使得剩下的序列经过某种操作后的值最大 看上去是个区间 dp .然后直接断环成列, ...
- C#/VB 数据库连接字符串大全
C#/VB 数据库连接字符串大全 https://www.connectionstrings.com/ SQL Server常用 Standard Security Server=myServerAd ...
- vue大型电商项目尚品汇(后台篇)day04
昨天太晚就没来得及更新,今天是spu管理界面,这个界面一共有三个界面需要切换,完成了两个界面,而且今天的难度在于最后两个章节,富有一定的逻辑性,当然中间也有很多需要注意的,比如ElementUI的照片 ...