热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

POJ10101020DFS+剪枝

之所以要写这两题的解题报告,原因就是这两题是比较好的搜索题,必须记录一下。另外,最近做题状态也不行,看见题目后没想法&#x

之所以要写这两题的解题报告,原因就是这两题是比较好的搜索题,必须记录一下。

另外,最近做题状态也不行,看见题目后没想法,然后看别人解题报告了,突然发现自己想过这方面,但是没深入去想,然后就做不出来了。


1.POJ 1010 题意晦涩难懂。从网上找了一个稍微能说清楚的题意

题意:
给出n种邮票,每种邮票有自己的面值(面值可能重复)
指定m种“总面值”,对每种“总面值”,求解满足如下条件的组合以达到该“总面值”
(1) 所用邮票在n种中可以重复选取
(2) 所用邮票张数〈=4
(3) 尽量多的使用那个不同种类的邮票 Max (Stamp Types)
(4) 若有多种方案满足(3),则选取张数最小的一种方案 Min (Stamp Num)
(5) 若有多种方案满足(3)(4),则选取“最大面额”最高的一种方案。 Max(Heightest Value)
(6) 若有多种方案满足(3)(4)(5) 则输出 “tie”1010


并且这题给的sample都还夹着注释,不仔细看题还以为那些也需要输入。

说一下思路吧,动态规划是最优选择,但是确实不好想,普遍的都是用DFS。

优化之一: 每种面值的邮票最多5种即可,如果有多的,就不需要了。比如一下子给了1 1 1 1 1 1 1 1,八个1,其实只需要5个就行,因为题目说了,最多4个,保留5个的目的就是为了多解准备的。再多也没意义。这样由于最多有25种邮票,也就是数组到126就够了。

然后dfs过程中如果选择的邮票面额之和大于所需的,也剪掉,总数大于4的剪掉,剩下的貌似就没什么了。

dfs过程中,有一个中间值,存储着邮票的种类,总个数,最大面值,所选的邮票等,然后有一个最终结果,每次dfs出的中间值,如果优于最终结果就要更新最终结果,那么怎样算是tie呢,就要用1个变量标记一下,如果被更新了,就置这个变量为1,如果出现打平的,就把他++一下,这样不断的覆盖这个变量即可。

另外,这道题目貌似给的序列都是有序的。

/*
ID: sdj22251
PROG: subset
LANG: C++
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXN 100007
#define INF 1000000000
#define eps 1e-7
using namespace std;
int size, x;
int stamp[550];
int some;
struct wwj
{int cnt, num;int mx, ana[555];void init(){cnt = 0;num = 0;mx = 0;memset(ana, 0, sizeof(ana));}
}tmp, ans;
void init()
{some = 0;tmp.init();ans.init();
}
void get()
{tmp.cnt = 0;tmp.mx = 0;for(int i = 0; i tmp.mx)tmp.mx = stamp[i];}}
}
void dfs(int index, int num, int sum)
{if(num > 4) return;if(sum &#61;&#61; x){tmp.num &#61; num;get();if(tmp.cnt > ans.cnt){ans &#61; tmp;some &#61; 1;}else if(tmp.cnt &#61;&#61; ans.cnt){if(tmp.num ans.mx){ans &#61; tmp;some &#61; 1;}else if(tmp.mx &#61;&#61; ans.mx) {some&#43;&#43;;}}}return;}if(index >&#61; size || sum > x) return;for(int i &#61; 0; i <&#61; 4; i&#43;&#43;){tmp.ana[index] &#43;&#61; i;dfs(index &#43; 1, num &#43; i, sum &#43; stamp[index] * i);tmp.ana[index] -&#61; i;}
}
void output()
{printf("%d ", x);if(some &#61;&#61; 0) printf("---- none\n");else if(some &#61;&#61; 1){printf("(%d):", ans.cnt);for(int i &#61; 0; i 0){for(int j &#61; 0; j }
int main()
{while(scanf("%d", &x) !&#61; EOF){size &#61; 0;stamp[size&#43;&#43;] &#61; x;while(scanf("%d", &x) !&#61; EOF && x){int nt &#61; 0;for(int i &#61; 0; i &#61; 5) continue;stamp[size&#43;&#43;] &#61; x;}while(scanf("%d", &x) !&#61; EOF && x){init();dfs(0, 0, 0);output();}}return 0;
}




2.poj 1020

又是一道搜索题

题目大意是给出一个大的正方形&#xff0c;然后又给出了一群小正方形&#xff0c;问大的正方形能不能由这些小正方形组成&#xff0c;并且每个正方形都要用到。

思路是贪心&#43;dfs

首先&#xff0c;对输入的数组&#xff0c;由于题目中说了&#xff0c;小正方形的边长范围是1~10&#xff0c;所以开个数组记录一下每个边长的正方形个数&#xff0c;dfs的时候枚举就方便了。

然后用一个数组&#xff0c;len[i]表示第i行被覆盖了len[i]列&#xff0c;而且是左边无空隙的。

然后每次贪心找最小的len[i]&#xff0c;因为这样的话&#xff0c;达到最优解的可行性最大。在这个位置上&#xff0c;看下面和右面是否有足够的位置&#xff0c;前提是左边是填充好的&#xff0c;所以就要求这些位置的len[i]必须都是一样的&#xff0c;然后就枚举边长&#xff0c;往里塞小正方形&#xff0c;找不到解就回溯。

网上有的贪心是不正确的&#xff0c;因为没有考虑到一些比较特别的数据&#xff0c;而且poj的这道题数据还很弱。正确的做法应该是贪心&#43;回溯&#xff0c;就能保证一定要到正确的答案。


/*
ID: sdj22251
PROG: subset
LANG: C&#43;&#43;
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXN 100007
#define INF 1000000000
#define eps 1e-7
using namespace std;
int n, x;
int len[55], cnt[15];
bool dfs(int deep)
{if(deep &#61;&#61; n) return true;int mi &#61; INF;int pos &#61; 0;for(int i &#61; 1; i <&#61; x; i&#43;&#43;){if(mi > len[i]){mi &#61; len[i];pos &#61; i;}}for(int i &#61; 1; i <&#61; 10; i&#43;&#43;){if(cnt[i]){if(len[pos] &#43; i <&#61; x){int width &#61; 0;for(int j &#61; pos; j <&#61; x; j&#43;&#43;)if(len[j] &#61;&#61; len[pos]) width&#43;&#43;;else break;if(width >&#61; i){cnt[i]--;for(int j &#61; pos; j }
int main()
{int T;scanf("%d", &T);while(T--){scanf("%d", &x);memset(len, 0, sizeof(len));memset(cnt, 0, sizeof(cnt));scanf("%d", &n);int area &#61; 0, t;for(int i &#61; 0; i }







推荐阅读
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
author-avatar
Mrheartheart
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有