20220729 - DP训练 #2

时间记录

  1. \(8:00-8:10\) 浏览题面

  2. \(8:10-8:50\) T1

    看题想到了建树,从每一个点遍历,若能遍历每一个点,则可以获胜

    快速写完之后,发现每次格斗只能和相邻的人进行对决

    再思考,感觉像是 区间DP,但是忘记怎么写了,于是写搜索

    感觉写出了满分做法,最终爆零。

  3. \(8:50-9:20\) T2

    看出是分组背包,利用前缀和优化,写完感觉没有问题,最终 \(90\) 分。

  4. \(9:20-9:50\) T3

    再次看题,没有思路,假设两种状态均不可行,最终写贪心

    分别按照能够杀掉野怪个数,花费最少排序,最后去两种贪心的最小花费

    没想到居然把样例都过了!!!

  5. \(9:50-10:10\)

    原计划 \(10:00\) 比赛结束,最后延时 \(20\) 分钟

    于是重新检查之前代码,发现 \(T1\) 的搜索可以再优化

    删删减减之后,就不成搜索了。。。

    for循环 就基本可以解决,没有时间再写

最终成绩——前 \(47\%\)

T1 T2 T3
0 90 4

\(T2\) 只差一组数据,和他人代码多次对比,更正,发现是因为 \(sum\) 数组少开了 \(40\)。

计算大小错误,导致丢了 \(10\) 分。

\(T3\) 没有想到 状压,而且现在也不会写状压了,重新复习。

T1-格斗

题目描述

格斗俱乐部是格斗爱好者的一个组织,在这里,格斗者们能通过与别的成员进行格斗来释放自己的压力与轻松自己的情绪。

最近俱乐部举行了一场比赛,该比赛有 \(N\) 位选手参加,他们将围成一个圆圈,每一场比赛圈内任意的两位相邻的选手均可进行相互的格斗,胜利者将留在圈内进入下轮比赛而失败者则直接被送往医院(没有平局)。比赛是残酷的,最后圈内将只剩下一位选手,他将是总冠军。

我们做个奇怪的假设,两位选手进行格斗,他们比赛的结果总是确定的。虽然俱乐部的成员们都很喜欢格斗,但是他们仍然很希望能获得总冠军。

现在你通过统计已经知道了任意两位选手格斗的结果,你有责任告诉每位选手,如果赛程合适安排的话,他是否可能成为总冠军。

输入格式

数据第一行是一个整数\(N(1 \leq N \leq 40)\),表示比赛的选手数量。

接下来给出一个 \(N\times N\) 的 “\(0\)”、“\(1\)” 矩阵\(A\)(行内用空格隔开),第 \(i\) 行第 \(j\) 列为 \(1\) 表示选手 \(i\) 能战胜选手 \(j\),否则选手 \(j\) 能战胜选手 \(i\) 。

你可以假定 \(A_{i,j}\)与 \(A_{j,i}(i \neq j)\) 均是不同的且 \(A_{i,i}=0\) 。比赛开始时所有选手按顺时针方向由编号 \(1\) 到编号 \(N\) 站成一个圈,初始时编号 \(1\) 与编号 \(N\) 的选手是相邻的。

输出格式

输出包含 \(N\) 行,每行为一个整数 “\(0\)” 或 “\(1\)”,“\(1\)” 表示第 \(i\) 号选手有可能成为冠军,“\(0\)” 表示不可能。

样例数据

input

3
0 1 1
0 0 1
0 0 0

output

1
0
0

本题为 区间DP,由于存在环,将长度扩展一倍即可破环

数据范围很小,可以尝试 三维状态

状态:\(f[i][j][k]\):若从第 \(i\) 个人到第 \(j\) 个人决出胜者,第 \(k\) 个人能否为最终胜者

状态转移:见代码

int m=n<<1;
for(int i=1;i<=m;i++)
f[i][i][i]=1;
for(int len=2;len<=m;len++)
{
for(int i=1;i+len-1<=m;i++)
{
int j=i+len-1;
for(int k=i;k<j;k++)
for(int l=i;l<=k;l++)
if(f[i][k][l])
for(int r=k+1;r<=j;r++)
if(f[k+1][j][r])
if(a[l][r]) f[i][j][l]=true;
else f[i][j][r]=true;
}
}

当然,还有另一种状态,相对于第一种比较难想,不过多阐述。

状态:\(f[i][j]\):若从第 \(i\) 个人到第 \(j\) 个人决出胜者,胜者能否为 \(i\) 或 \(j\)

状态转移:

if((a[i][k]==1||a[j][k]==1)&&f[i][k]==true&&f[k][j]==true) f[i][j]=true;

T2-背包问题

题目描述

从 \(T\) 组物品中选出一些物品,放入背包中,求剩余空间的最小值。

限制条件:从每组物品中挑选物品必须要选取连续的一段。

就是说,如果这组物品共有 \(n\) 个: 物品 \(1\)、物品 \(2\)、物品 \(3\)、\(\cdots\)、物品 \(n\),

那么只能选取物品 \(i\)、物品 \(i+1\)、\(\cdots\)、物品 \(j\),其中 \(1 \leq i \leq j \leq n\),或者不选。

输入格式

第一行为两个用空格隔开的正整数 \(v\)和 \(T\) 。表示背包的空间和物品的组数。

接下来有 \(T\) 行,每行先是一个正整数 \(n_i\),表示这组物品有 \(n_i\) 个,然后 \(n_i\) 个正整数,表示每个物品的大小。

输出格式

仅一个数,表示剩余空间的最小值。

样例数据

input

100 3
3 7 6 8
2 80 70
4 101 108 103 150

output

6

样例说明

第 \(1\) 组选 \(6,8\),第 \(2\) 组选 \(80\),第 \(3\) 组不选。

数据规模与约定

\(60\%\) 的数据满足:\(1 \leq n_i \leq 10\)

\(100\%\) 的数据满足:\(1 \leq n_i \leq 100\),\(1 \leq v \leq 5000\),\(1 \leq T \leq 10\)

分组背包 模型,稍有变化,需要利用前缀和进行优化

优化思想与 AcWing277 饼干 类似,可以参考

将问题转化为 可行性问题 即可

状态:\(f[i][j]\):使用前 \(i\) 组物品,能否使占用的总空间为 \(j\)

状态转移:\(f[i][j]|=f[i-1][j-sum[k]]\)

f[0][0]=true;
for(int i=1;i<=T;i++)
{
int cnt=0;
for(int l=1;l<=n[i];l++)
{
for(int k=l;k<=n[i];k++)
{
sum[cnt+1]=sum[cnt]+a[i][k];
if(k==l) sum[cnt+1]-=sum[cnt];
cnt++;
}
}
for(int j=0;j<=v;j++)
{
f[i][j]|=f[i-1][j];
for(int k=1;k<=cnt;k++)
if(j>=sum[k]) f[i][j]|=f[i-1][j-sum[k]];
}
for(int j=1;j<=cnt;j++)
sum[j]=0;
}

T3-Get Everything AtCoder abc142E

题目描述

野区里有 \(n\) 个野怪, 编号为 \(1\) 到 \(n\) 。

商店里出售 \(m\) 把武器,每一把武器只能打死特定的一些野怪。

第 \(i\) 把武器花费 \(a_i\) 金币,能打死 \(b_i\) 个野怪,这 \(b_i\) 个野怪的编号分别为 \(c_{i,1},c_{i,2},\cdots ,c_{i,b_i}\),已购买的武器可以使用任意次。

theshy 需要花费最少的钱购买一些武器,将这些野怪全部打死,如果能全部打死,输出这个最小花费;如果不能,输出 \(−1\)

输入格式

第一行输入野怪的个数 \(n\) 和武器的个数 \(m\)

接下来共有 \(m\) 组,第 \(i\) 组描述第 \(i\) 把武器的信息:

对于每一组武器:

第一行输入一个 \(a\) 和 \(b\),分别代表这种武器的价钱和这把武器能打死几个野怪

第二行输入 \(b\) 个编号,代表这个技能能打死野怪的编号

输出格式

输出最小的花费打死所有的野怪。如果不能全部打死,输出 \(-1\)

样例数据

input

2 3
10 1
1
15 1
2
30 2
1 2

output

25

购买第一把武器和第二把武器可以打死所有的野怪,共花费最小消耗 \(25\)

input

12 1
100000 1
2

output

-1

input

4 6
67786 3
1 3 4
3497 1
2
44908 3
2 3 4
2156 3
2 3 4
26230 1
2
86918 1
3

output

69942

数据规模与约定

所有的数都是整数

\(1 \leq n \leq 12\)

\(1 \leq m \leq 1000\)

\(1 \leq a_i \leq 100000\)

\(1 \leq b_i \leq n\)

\(1 \leq c_{i,1} < c_{i,2} < \cdots < c_{i,b_i} \leq n\)

观察数据范围 \(n \leq 12\),范围很小,考虑到 状压DP

套用 状压DP 模板,即可基本解决本题

状态:\(f[mask]\):在当前集合下野怪能否被杀的情况集合

我们可以用:\(a[i]\) 表示第 \(i\) 把武器能够杀死野怪的集合

scanf("%d",&x);
a[i]|=(1<<(x-1));

状态转移:

\[f[tmask] = \min_{1 \leq i \leq m} (f[tmask],f[mask]+val[i]),\ tmask=mask|a[i]
\]

其中,\(a[i]\):第 \(i\) 把武器能够杀死野怪的集合

int t=(1<<n)-1;
for(int i=0;i<=t;i++)
f[i]=INF;
f[0]=0;
for(int mask=0;mask<=t;mask++)
{
for(int i=1;i<=m;i++)
{
int tmask=(mask|a[i]);
f[tmask]=min(f[tmask],f[mask]+val[i]);
}
}
if(f[t]==INF) printf("-1\n");
else printf("%d\n",f[t]);

20220729 - DP训练 #2的更多相关文章

  1. 20220728 - DP训练 #1

    20220728 - DP训练 #1 时间记录 \(8:00-9:00\) T1 尝试做 \(T1\),可惜并未做出,没有想到是资源分配 设置三维状态,初值一直不知道怎么设置 并且对于距离有一部分不会 ...

  2. dp训练

    根据这位大佬的https://www.cnblogs.com/Bunnycxk/p/7360183.html 题目链接:https://www.luogu.org/problemnew/show/P3 ...

  3. 8.8&8.9 dp训练小结

    写了两天的dp题,表示大多dp都不会啊,还是爆搜大法好.我真的太蒻了dp还是要多做题啊,一些基本的套路还是不熟,真正写对的dp也就一道,还一道爆搜过的,dp还有很深的坑要填啊.. 8.8 T1 质数和 ...

  4. 区间DP训练

    一.石子合并 问题描述 将 n (\(1 \le n \le 200\))堆石子绕圆形操场摆放,现要将石子有次序地合并成一堆.规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并 ...

  5. Column Addition~DP(脑子抽了,当时没有想到)

    Description A multi-digit column addition is a formula on adding two integers written like this:

  6. hdu2089数位DP

    旁听途说这个名字很久了,了解了一下. 改题目的意思是给你若干区间,让你找寻区间内不含62或4的数. 首先暴力必然T...那么实际上就是说,想办法做一种预处理,在每次输入的时候取值运算就可以了. 既然是 ...

  7. 初学dp心得

    从STL到贪心,再到现在的动态规划,可以说动态规划真的让我学的有点蒙,对于一些题目,会做,但是不会用DP,现在还不能熟练的写出状态转移方程,更重要的是,自己宛如一个哺乳期的小孩,做题需要套模板,没有模 ...

  8. dp (1)

    D - Tree of Tree ZOJ - 3201 这个题目我开始是这么定义的dp[i][j][0] dp[i][j][1] 表示对于第i个节点还有j个的选择 0 代表不选这个节点,1 代表选这个 ...

  9. ML2021 | (腾讯)PatrickStar:通过基于块的内存管理实现预训练模型的并行训练

    ​  前言  目前比较常见的并行训练是数据并行,这是基于模型能够在一个GPU上存储的前提,而当这个前提无法满足时,则需要将模型放在多个GPU上.现有的一些模型并行方案仍存在许多问题,本文提出了一种名为 ...

随机推荐

  1. 【web自动化测试】playwright安装失败怎么办

    在安装中,如果没有输入 playwright install, 则不会安装浏览器,运行 playwright codegen 时会报浏览器找不到的错误: "chromium" br ...

  2. Map集合的遍历方式以及TreeMap集合保存自定义对象实现比较的Comparable和Comparator两种方式

    Map集合的特点 1.Map集合中保存的都是键值对,键和值是一一对应的 2.一个映射不能包含重复的值 3.每个键最多只能映射到一个值上 Map接口和Collection接口的不同 Map是双列集合的根 ...

  3. Vue3 + Socket.io + Knex + TypeScript 实现可以私聊的聊天室

    前言 下文只在介绍实现的核心代码,没有涉及到具体的实现细节,如果感兴趣可以往下看,在文章最后贴上了仓库地址.项目采用前后端模式,前端使用 Vite + Vue3 + TS:后端使用 Knex + Ex ...

  4. [WPF]使用DispatcherUnhandledException捕捉未经处理的异常

    使用DispatcherUnhandledException捕捉未经处理的异常 using System.Windows; namespace Test02 { /// <summary> ...

  5. 用metasploit映射公网远程控制舍友电脑

    用metasploit映射公网远程控制舍友电脑 Metasploit是一款开源的安全漏洞检测工具,可以帮助安全和IT专业人士识别安全性问题,验证漏洞的缓解措施,并管理专家驱动的安全性进行评估,提供真正 ...

  6. KingbaseES 的 Lateral 连接

    一.什么是 Lateral 连接 根据文档,它的作用是: LATERAL 关键字可以位于子 SELECT FROM 项之前.这允许子 SELECT 引用 FROM 列表中出现在它之前的 FROM 项的 ...

  7. Centos下使用containerd管理容器:5分钟从docker转型到containerd

    目录 一.系统环境 二.前言 三.containerd 四.部署containerd 4.1 安装containerd 4.2 containerd配置文件 4.3 配置containerd阿里云镜像 ...

  8. Java 热更新 Groovy 实践及踩坑指南

    Groovy 是什么? Apache的Groovy是Java平台上设计的面向对象编程语言.这门动态语言拥有类似Python.Ruby和Smalltalk中的一些特性,可以作为Java平台的脚本语言使用 ...

  9. redis的简单学习记录

    安装 1 brew install redis 启动redis服务 1 redis-server & 启动命令 1 redis-cli -h 127.0.0.1 -p 6379 利用gored ...

  10. Logstash:input plugin 介绍