https://vijos.org/p/1426

这是个好题,容易想到用dp[i][v1][v2][v3][v4][v5]表示在前i个物品中,各种东西的容量是那个的时候,能产生的最大价值。

时间不会TLE,但是会MLE.所以就需要把那5维状态进行hash

其实就是对这个排列进行一个hash。

newState: v1, v2, v3, v4, v5这个排列。

oldState: v1 - w[1], v2 - w[2], v3 - w[3], v4 - w[4], v5 - w[5]

这个排列。

然后要进行hash。我写了一个hash。TLE 两组数据。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = + ;
int dp[ + ];
int limit[maxn];
int w[maxn][];
int val[maxn];
int togive;
const int seed = ;
typedef unsigned long long int ULL;
ULL powseed[];
int first[ + ];
ULL Edge[ + ];
int tonext[ + ];
int id[ + ];
int num;
int toadd(ULL val) {
int u = val % ;
for (int i = first[u]; i; i = tonext[i]) {
if (val == Edge[i]) return id[i];
}
++num;
tonext[num] = first[u];
first[u] = num;
Edge[num] = val;
id[num] = ++togive;
return togive;
}
int tohash(int a, int b, int c, int d, int e) {
ULL val = a * powseed[] + b * powseed[] +
c * powseed[] + d * powseed[] + e * powseed[];
return toadd(val);
}
//适用于正负整数
template <class T>
inline bool fast_in(T &ret) {
char c;
int sgn;
if(c = getchar(), c == EOF) return ; //EOF
while(c != '-' && (c < '' || c > '')) c = getchar();
sgn = (c == '-') ? - : ;
ret = (c == '-') ? : (c - '');
while(c = getchar(), c >= '' && c <= '') ret = ret * + (c - '');
ret *= sgn;
return ;
}
void work() {
int n, m;
// cin >> n >> m;
// scanf("%d%d", &n, &m);
fast_in(n);
fast_in(m);
for (int i = ; i <= m; ++i) {
// cin >> limit[i];
// scanf("%d", &limit[i]);
fast_in(limit[i]);
}
for (int i = ; i <= n; ++i) {
// cin >> val[i];
// scanf("%d", &val[i]);
fast_in(val[i]);
for (int j = ; j <= m; ++j) {
// cin >> w[i][j];
// scanf("%d", &w[i][j]);
fast_in(w[i][j]);
}
}
// cout << tohash(1, 2, 3, 4, 5) << endl;
// cout << tohash(1, 2, 4, 3, 5) << endl;
// cout << tohash(1, 2, 3, 4, 5) << endl;
int ans = ;
for (int i = ; i <= n; ++i) {
for (int a1 = limit[]; a1 >= w[i][]; --a1) {
for (int a2 = limit[]; a2 >= w[i][]; --a2) {
for (int a3 = limit[]; a3 >= w[i][]; --a3) {
for (int a4 = limit[]; a4 >= w[i][]; --a4) {
for (int a5 = limit[]; a5 >= w[i][]; --a5) {
int now = tohash(a1, a2, a3, a4, a5);
int pre = tohash(a1 - w[i][], a2 - w[i][], a3 - w[i][], a4 - w[i][], a5 - w[i][]);
dp[now] = max(dp[now], dp[pre] + val[i]);
ans = max(ans, dp[now]);
}
}
}
}
}
}
printf("%d\n", ans);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
powseed[] = ;
for (int i = ; i <= ; ++i) {
powseed[i] = powseed[i - ] * seed;
}
work();
return ;
}

题解的那个hash我真看不懂。不是看不懂,是不理解。

其实他的意思类似于a * 1000000 + b * 100000 + c * 1000 + e * 100 * d * 10

这样类似的。但是明显这个值太大了。他就乘上了limit[i],这个我不能证明了,

好像又不会重复,数字又小。ORZ

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = + ;
int dp[ + ];
int limit[maxn];
int w[maxn][];
int val[maxn]; int tohash(int a, int b, int c, int d, int e) {
return (a * (limit[] + ) * (limit[] + ) * (limit[] + ) * (limit[] + )
+ b * (limit[] + ) * (limit[] + ) * (limit[] + )
+ c * (limit[] + ) * (limit[] + ) + d * (limit[] + ) + e);
}
//适用于正负整数
template <class T>
inline bool fast_in(T &ret) {
char c;
int sgn;
if(c = getchar(), c == EOF) return ; //EOF
while(c != '-' && (c < '' || c > '')) c = getchar();
sgn = (c == '-') ? - : ;
ret = (c == '-') ? : (c - '');
while(c = getchar(), c >= '' && c <= '') ret = ret * + (c - '');
ret *= sgn;
return ;
}
void work() {
int n, m;
// cin >> n >> m;
// scanf("%d%d", &n, &m);
fast_in(n);
fast_in(m);
for (int i = ; i <= m; ++i) {
// cin >> limit[i];
// scanf("%d", &limit[i]);
fast_in(limit[i]);
}
for (int i = ; i <= n; ++i) {
// cin >> val[i];
// scanf("%d", &val[i]);
fast_in(val[i]);
for (int j = ; j <= m; ++j) {
// cin >> w[i][j];
// scanf("%d", &w[i][j]);
fast_in(w[i][j]);
}
}
// cout << tohash(1, 2, 3, 4, 5) << endl;
// cout << tohash(1, 2, 4, 3, 5) << endl;
// cout << tohash(1, 2, 3, 4, 5) << endl;
int ans = ;
for (int i = ; i <= n; ++i) {
for (int a1 = limit[]; a1 >= w[i][]; --a1) {
for (int a2 = limit[]; a2 >= w[i][]; --a2) {
for (int a3 = limit[]; a3 >= w[i][]; --a3) {
for (int a4 = limit[]; a4 >= w[i][]; --a4) {
for (int a5 = limit[]; a5 >= w[i][]; --a5) {
int now = tohash(a1, a2, a3, a4, a5);
int pre = tohash(a1 - w[i][], a2 - w[i][], a3 - w[i][], a4 - w[i][], a5 - w[i][]);
dp[now] = max(dp[now], dp[pre] + val[i]);
ans = max(ans, dp[now]);
}
}
}
}
}
}
printf("%d\n", ans);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}

感觉我的hash才是正确的打开方式

vijos P1426兴奋剂检查 多维费用背包问题的hash的更多相关文章

  1. VIJOS P1426兴奋剂检查[DP 状态哈希]

    背景 北京奥运会开幕了,这是中国人的骄傲和自豪,中国健儿在运动场上已经创造了一个又一个辉煌,super pig也不例外……………… 描述 虽然兴奋剂是奥运会及其他重要比赛的禁药,是禁止服用的.但是运动 ...

  2. HDU 2159 二维费用背包问题

    一个关于打怪升级的算法问题.. 题意:一个人在玩游戏老是要打怪升级,他愤怒了,现在,还差n经验升级,还有m的耐心度(为零就删游戏不玩了..),有m种怪,有一个最大的杀怪数s(杀超过m只也会删游戏的.. ...

  3. J. Bottles 二维费用背包问题

    http://codeforces.com/contest/730/problem/J 3 4    36    1 90   45   40 其实可以知道,选出多少个瓶子呢?是确定的,当然选一些大的 ...

  4. UESTC - 878 温泉旅店 二维费用背包问题

    http://acm.uestc.edu.cn/#/problem/show/878 设dp[i][j][k]表示在前i个数中,第一个得到的异或值是j,第二个人得到的异或值是k的方案数有多少种. 因为 ...

  5. vijos1426兴奋剂检查(多维费用的背包问题+状态压缩+hash)

    背景 北京奥运会开幕了,这是中国人的骄傲和自豪,中国健儿在运动场上已经创造了一个又一个辉煌,super pig也不例外……………… 描述 虽然兴奋剂是奥运会及其他重要比赛的禁药,是禁止服用的.但是运动 ...

  6. hdu_2159(二维费用背包)

    HDU_2159 二维费用背包问题 http://acm.hdu.edu.cn/showproblem.php?pid=2159 #include<cstdio> #include< ...

  7. 2159 ACM 杭电 杀怪 二维费用的背包+完全背包问题

    题意:已知经验值,保留的忍耐度,怪的种数和最多的杀怪数.求进入下一级的最优方案. 思路:用二维费用的背包+完全背包问题 (顺序循环)方法求解 什么是二维费用的背包问题? 问题: 二维费用的背包问题是指 ...

  8. 动态规划:HDU3496-Watch The Movie(二维费用的背包问题)

    Watch The Movie Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) ...

  9. 动态规划:HDU2159-FATE(二维费用的背包问题)

    FATE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

随机推荐

  1. js中window.onload 与 jquery中$(document.ready()) 測试

    js中window.onload 与 jquery中$(document.ready())差别,验证代码例如以下(调换js代码和Jquer代码书写顺序測试.执行结果一样.因此与代码书写位置没关系): ...

  2. 2016/3/30 ①投票checkbox ②进度条两个div套起百分比控制内div(width) <div><div></div></div> ③数据库test2 表 diaoyan... 35岁发展方向投票

    分两个页面,要点:提交form 相连action method  两个页面可以合成一个页面action传到自身页面   但分开较清晰 第一个页面vote.php <!DOCTYPE html P ...

  3. Codevs 2006=BZOJ 2964 Boss单挑战

    2964: Boss单挑战 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 266  Solved: 120[Submit][Status][Discu ...

  4. SSH三大框架整合配置详细步骤(3)

    5 配置Spring2.5 5.1 基础配置 1)        导入spring包.下载spring-framework-2.5.6并解压后,在spring-framework-2.5.6" ...

  5. 内存转储文件 Memory.dmp

    https://baike.sogou.com/v63435711.htm?fromTitle=内存转存文件 内存转储是用于系统崩溃时,将内存中的数据转储保存在转储文件中,供给有关人员进行排错分析用途 ...

  6. 显示 目录 大小 du

    [root@hadoop1 /]# du -BG  -d 11G ./boot0G ./dev63G ./homedu: 无法访问"./proc/6689/task/6689/fd/4&qu ...

  7. spring 简述

    Spring的发展 1.1. Spring1.x 时代 在Spring1.x时代,都是通过xml文件配置bean,随着项目的不断扩大,需要将xml配置分放到不同的配置文件中,需要频繁的在java类和x ...

  8. HubbleDotNet 开源全文搜索数据库项目--为数据库现有表或视图建立全文索引(三) 多表关联全文索引模式

    关系型数据库中,多表关联是很常见的事情,HubbleDotNet 可以对部分情况的多表关联形式建立关联的全文索引,这样用户就不需要专门建一个大表 来解决多表关联时的全文索引问题. 下面以 为数据库现有 ...

  9. BZOJ3732:Network(LCT与最小生成树)

    给你N个点的无向图 ( <= N <= ,),记为:…N. 图中有M条边 ( <= M <= ,) ,第j条边的长度为: d_j ( < = d_j < = ,,, ...

  10. net share

    IT知识梳理 2017-11-30 06:57:10 Dos 命令进阶(一)讲解思路 1.Net常用命令 (1)net share - 查看共享命令 net share ipc$ - 设置ipc$共享 ...