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. JavaSciprt 笔记目录

    JavaScript 基础知识(一):对象以及原型 JavaScript 基础知识(二):闭包 JavaScript 异步编程(一):认识异步编程 JavaScript 异步编程(二):Promise

  2. 从HashMap的执行流程开始 揭开HashMap底层实现

    心得:如何学习源码: 从某个执行过程入手,建议先从整体入手,了解底层的数据结构是怎么一步一步优化的.最后,在了解完底层的数据结构优化过程后,从重要的核心方法入手,从它的执行流程入手,先去网上搜索了解它 ...

  3. 分布式id生成器,雪花算法IdWorker

    /** * <p>名称:IdWorker.java</p> * <p>描述:分布式自增长ID</p> * <pre> * Twitter的 ...

  4. 一、JDK和JRE

    JDK和JRE JDK=JRE+开发工具包: JRE=JVM+核心类库 如果只是运行Java程序,安装JRE即可:开发Java程序并运行则需要安装JDK.目前最稳定版本是JDK8.0,并且马上部分企业 ...

  5. 使用MindSpore计算旋转矩阵

    技术背景 坐标变换.旋转矩阵,是在线性空间常用的操作,在分子动力学模拟领域有非常广泛的应用.比如在一个体系中切换坐标,或者对整体分子进行旋转平移等.如果直接使用Numpy,是很容易可以实现的,只要把相 ...

  6. spring接口多实现类,该依赖注入哪一个?

    一.问题的描述 在实际的系统应用开发中我经常会遇到这样的一类需求,相信大家在工作中也会经常遇到: 同一个系统在多个省份部署. 一个业务在北京是一种实现方式,是基于北京用户的需求. 同样的业务在上海是另 ...

  7. 简单html js css 轮播图片,不用jquery

    这个是自己修改的轮播图片,在网上有的是flash 实现的轮播图片,对搜索引擎不友好, 比如:dedecms 的首页的轮播图是用flash实现滚动的. 所以这个自己修改了一下,实现html+js+css ...

  8. 微信小程序/校园社区论坛/微信云开发/云函数

    一.框架来源 1.非常非常感谢B站up主"梦千的曾哥哥"的开源框架. 没有他就没有这个小程序.如果有想做的同学,可以直接移步他的视频那里开始学习.我水平不够,就不教具体怎么配置环境 ...

  9. 【Java】学习路径59-多个连接的服务器端

    ServerSocket可以对接多个Socket对象,利用这点,就可以实现:一台服务器对多个客户端. import java.io.IOException; import java.net.*; pu ...

  10. 实践分享!GitLab CI/CD 快速入门

    用过 GitLab 的同学肯定也对 GitLab CI/CD 不陌生,GitLab CI/CD 是一个内置在 GitLab 中的工具,它可以帮助我们在每次代码推送时运行一系列脚本来构建.测试和验证代码 ...