USACO算法系列十五——shoping
题目:http://www.nocow.cn/index.php/Translate:USACO/shopping
题目很长,大致意思是买n种商品,然后这几种商品按照不同的组合可以有不同的折扣,要我们按照最优的折扣来买东西。看到这道题很自然想到的是背包问题,但是这道题包含的信息明显复杂的多。让我想起了一句话“数据结构是算法的基础,好的数据结构能够很大程度上减少算法的复杂度。”
我使用的第一种方法是,深度搜索剪枝方法,代码如下:
#include <iostream> #include <fstream> #define TYPE 1000 #define SIZE 100 using namespace std; struct Good { int id; int num; }; struct GoodPrivilige { int num; Good g[5]; int value; }; //记录商品价格 int value[TYPE] = {0}; GoodPrivilige p[SIZE]; int pl; Good need[5]; int nl; int result = 0x7FFFFFFF; void calResult(int level, int money) { if (level >= pl) { for (int i=0;i <nl; i ++) { money += need[i].num * value[need[i].id]; } if (money < result) { result = money; } } else { int n = 0; int m = money; while (true) { int flag = true; for (int i=0; i < nl; i ++) { if (need[i].num < 0) { flag = false; break; } }//检验是否有效 //检查有效性 并进行剪枝 if(flag && m < result ) { calResult(level+1,m); } else break; n++; //使用方案的数量 for (int i=0; i < p[level].num; i ++) { int id = p[level].g[i].id; for (int j=0; j < nl; j ++) { if (id == need[j].id) { need[j].num -= p[level].g[i].num; break; }//end if }//end for j }//end for i m += p[level].value; }//end while //还原使用方案的数量 for (int i=0; i < p[level].num; i ++) { int id = p[level].g[i].id; for (int j=0; j < nl; j ++) { if (id == need[j].id) { need[j].num += n * p[level].g[i].num; break; }//end if }//end for j }//end for i }//end else } int main() { ifstream fin("shopping.in"); ofstream fout("shopping.out"); //输入数据 //输入方案 fin >> pl; for (int i =0; i< pl; i ++) { fin >> p[i].num; for (int j=0; j < p[i].num; j ++) { fin >> p[i].g[j].id; fin >> p[i].g[j].num; } fin >> p[i].value; } //输入要购买的物品 fin >> nl; for (int i=0; i < nl; i ++) { fin >> need[i].id >> need[i].num; fin >> value[need[i].id]; } calResult(0,0); fout << result << endl; return 0; }
很可惜的是在Test10的时候,就超时了。
Executing... Test 1: TEST OK [0.000 secs, 3024 KB] Test 2: TEST OK [0.011 secs, 3024 KB] Test 3: TEST OK [0.011 secs, 3024 KB] Test 4: TEST OK [0.000 secs, 3024 KB] Test 5: TEST OK [0.000 secs, 3024 KB] Test 6: TEST OK [0.022 secs, 3024 KB] Test 7: TEST OK [0.022 secs, 3024 KB] Test 8: TEST OK [0.011 secs, 3024 KB] Test 9: TEST OK [0.011 secs, 3024 KB] > Run 10: Execution error: Your program (`shopping') used more than the allotted runtime of 1 seconds (it ended or was stopped at 1.674 seconds) when presented with test case 10. It used 3024 KB of memory.
没办法,只好对其进行优化,跟背包的改进算法是一样的,只是用到了一个5维的数组,用于记录迭代前进的过程。代码如下:
#include <iostream> #include <fstream> #define TYPE 1000 #define SIZE 100 using namespace std; struct Good { int id; int num; }; struct GoodPrivilige { int num; Good g[5]; int value; }; //记录商品价格 int value[TYPE] = {0}; GoodPrivilige p[SIZE]; int pl; Good need[5]; int nl; int result; int table[6][6][6][6][6] = {0}; int getPrivilige(int index,int id) { for (int i=0; i < p[index].num; i ++) { if (id == p[index].g[i].id) { return p[index].g[i].num; } } return 0; } void calResult() { for (int n = 0; n < pl; n ++) { int p1 = getPrivilige(n, need[0].id); int p2 = getPrivilige(n, need[1].id); int p3 = getPrivilige(n, need[2].id); int p4 = getPrivilige(n,need[3].id); int p5 = getPrivilige(n,need[4].id); for (int i=p1; i <= need[0].num; i ++) { for (int j=p2; j <= need[1].num; j ++) { for (int k=p3; k <= need[2].num; k ++) { for (int l =p4; l <= need[3].num; l ++) { for (int m = p5; m <= need[4].num; m ++) { if(table[i][j][k][l][m] > table[i-p1][j-p2][k-p3][l-p4][m-p5] + p[n].value) { table[i][j][k][l][m] = table[i-p1][j-p2][k-p3][l-p4][m-p5] + p[n].value; } }//end m }//end l }//end k }//end j }//end i }//end n; } int main() { ifstream fin("shopping.in"); ofstream fout("shopping.out"); //输入数据 //输入方案 fin >> pl; for (int i =0; i< pl; i ++) { fin >> p[i].num; for (int j=0; j < p[i].num; j ++) { fin >> p[i].g[j].id; fin >> p[i].g[j].num; } fin >> p[i].value; } //输入要购买的物品 fin >> nl; for (int i=0; i < nl; i ++) { fin >> need[i].id >> need[i].num; fin >> value[need[i].id]; } //初始化 for (int i=0; i <= need[0].num; i ++) { for (int j=0; j <= need[1].num; j ++) { for (int k=0; k <= need[2].num; k ++) { for (int l =0; l <= need[3].num; l ++) { for (int m = 0; m <= need[4].num; m ++) { table[i][j][k][l][m] = i * value[need[0].id] + j * value[need[1].id] + k * value[need[2].id] + l * value[need[3].id] + m * value[need[4].id]; }//end m }//end l }//end k }//end j }//end i calResult(); result = table[need[0].num][need[1].num][need[2].num][need[3].num][need[4].num]; fout << result << endl; return 0; }
速度还不错。结果如下:
Executing... Test 1: TEST OK [0.022 secs, 3052 KB] Test 2: TEST OK [0.000 secs, 3052 KB] Test 3: TEST OK [0.000 secs, 3052 KB] Test 4: TEST OK [0.000 secs, 3052 KB] Test 5: TEST OK [0.011 secs, 3052 KB] Test 6: TEST OK [0.000 secs, 3052 KB] Test 7: TEST OK [0.000 secs, 3052 KB] Test 8: TEST OK [0.000 secs, 3052 KB] Test 9: TEST OK [0.011 secs, 3052 KB] Test 10: TEST OK [0.000 secs, 3052 KB] Test 11: TEST OK [0.011 secs, 3052 KB] Test 12: TEST OK [0.000 secs, 3052 KB] All tests OK.
USACO算法系列十五——shoping相关推荐
- ELK系列(十五)、Elasticsearch核心原理一篇全搞定
目录 Lucene 介绍 核心术语 如何理解倒排索引? 检索方式 分段存储 段合并策略 Elasticsearch 核心概念 节点类型 集群状态 3C和脑裂 1.共识性(Consensus) 2.并发 ...
- 数学之美 系列十五 繁与简 自然语言处理的几位精英
数学之美 系列十五 繁与简 自然语言处理的几位精英 我在数学之美系列中一直强调的一个好方法就是简单.但是,事实上,自然语言处理中也有一些特例,比如有些学者将一个问题研究到极致,执著追求完善甚至可以说完 ...
- Java 数据结构和算法(十五):无权无向图
Java数据结构和算法(十五)--无权无向图 前面我们介绍了树这种数据结构,树是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合,把它叫做"树"是因为它看起 ...
- Reflex WMS入门系列十五:Reflex系统上对已经Confirm的Receipt能继续做收货么?
Reflex WMS入门系列十五:Reflex系统上对已经Confirm的Receipt能继续做收货么? 如下的Receipt已经完成了收货,并且已经confirm了, Cfm(confirm)栏位被 ...
- WorldWind学习系列十五:如何切割影像和DEM数据及其在WW中的应用配置
原文转自:http://www.cnblogs.com/wuhenke/archive/2010/01/03/1638499.html WorldWind学习系列十四中我从代码上分析如何加载DEM数据 ...
- 聊聊MySQL的加锁规则《死磕MySQL系列 十五》
大家好,我是咔咔 不期速成,日拱一卒 本期来聊聊MySQL的加锁规则,知道这些规则后可以判断SQL语句的加锁范围,同时也可以写出更好的SQL语句,防止幻读问题的产生,在能力范围内最大程度的提升MySQ ...
- 数据与广告系列十五:商业兴趣标签建模XGboost调优实战
作者·黄崇远 『数据虫巢』 全文共8210字 题图ssyer.com " 聊聊商业兴趣标签建模,顺带学习下kaggle竞赛神器,快哉." 01 前言 我们来回想下,早在第是一篇&l ...
- 【某航】A*算法实现十五数码问题--人工智能课程大作业
代码链接:github代码 1.问题要求 15数码问题是在4×4方格盘上,放有15个数码,剩下一个位置为空(方便起见,用0表示空),每一空格其上下左右的数码可移至空格.本问题给定初始位置和目标位置,要 ...
- Oracle Golden Gate 系列十五 -- GG Trails 说明
一.Trails 说明 理论知识在系列一里有说明,这里在拿出来看一下: Oracle Golden Gate 系列一 -- GG 架构 说明 http://blog.csdn.net/tianleso ...
最新文章
- pandas使用replace函数和正则表达式移除dataframe字符串数据列中尾部指定模式字符串(Removing trailing substring in dataframe)
- 将keepalived添加到系统服务中
- c语言 void**类型转换,void *和其他指针的转化
- 【Julia】Julia v1.5.1 更改Pkg存放位置
- 杭电计算机组成实验2(二)超前进位加法器设计实验
- [bzoj5301][Cqoi2018]异或序列
- cvf命令报错 linux,linux命令大全
- 插件 微信 自动 抢红包
- Android屏幕共享-基于WebRTC实现
- python 爬取taptap热门榜
- 前端请求接口出现415错误
- 走进龙芯3A3000(二)安装Gentoo N64
- celery(分布式任务队列)介绍+在django中异步回调使用+定时任务的使用
- 并查集模板详细注释(洛谷P3367)
- 免费快速提升网站流量之方法大结合(转摘有修改)
- js闭包的理解(传递闭包的通俗理解)
- 面试 | 什么是内部类?成员内部类、静态内部类、局部内部类和匿名内部类的区别及作用?
- 第三方App接入微信登录 解读 (微信开放平台)
- jstree 新建node后,刷新jstree的改变的那一部分
- 浅谈Linux内核编程规范与代码风格