1.

[HNOI2001] 产品加工

一道简单的背包,然而我还是写了很久QAQ

时间范围是都小于5 显然考虑一维背包,dp[i]表示目前A消耗了i的最小B消耗

注意

if(b[i]) dp[j]=dp[j]+b[i];
 else dp[j]=1e9+7;

可以用B则直接转移,否则要把上一次的这个状态设为正无穷,只能用后两个转移。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=+;
const int N=*+;
int n,a[maxn],b[maxn],c[maxn],dp[N],lz[N],ans=1e9+;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]);
memset(dp,,sizeof(dp));
dp[]=;
for(int i=;i<=n;i++)
for(int j=i*;j>=;j--){
if(b[i]) dp[j]=dp[j]+b[i];
else dp[j]=1e9+;//!!!!!!!!!!!!!!!!!!!!
if(a[i]&&j>=a[i]&&dp[j]>dp[j-a[i]]) dp[j]=dp[j-a[i]];
if(c[i]&&j>=c[i]&&dp[j]>dp[j-c[i]]+c[i]) dp[j]=dp[j-c[i]]+c[i];
if(i==n) ans=min(max(dp[j],j),ans);
}
cout<<ans;
return ;
}

2.

[HAOI2007]上升序列

看数据范围似乎是n^2可以过的,然而自己之前并不会写nlongn求最长上升子序列的算法就自己YY了一下,写得很丑,单调栈里从短到长从大到小,用了两个二分,一次找找最长的比它小的,一次找长度为它的位置是否可以更新。

这样找到以每个元素打头的最长上升序列,询问就从1到n跑一遍问它能不能到那么长,就保证了字典序最小。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<vector>
using namespace std;
const int maxn=+;
int now,n,m,x,maxx,a[maxn],pre[maxn],dp[maxn],sta[maxn],sl=,sr;
int ef(int l,int r,int x){
int res=-;
while(l<=r){
int mid=(l+r)>>;
if(a[sta[mid]]>x) res=mid,l=mid+;
else r=mid-;
}
return res;
}
void ef2(int l,int r,int len,int x){
while(l<=r){
int mid=(l+r)>>;
if(dp[sta[mid]]==len) { if(a[sta[mid]]<=a[x]) sta[mid]=x; break;}
if(dp[sta[mid]]<len) l=mid+;
else if(dp[sta[mid]]>len) r=mid-;
}
}
void work() {
for(int i=n;i>=;i--) {
dp[i]=;
if(sl<=sr) {
now=ef(sl,sr,a[i]);
if(now!=-)
dp[i]=dp[sta[now]]+;
}
maxx=max(maxx,dp[i]);
while(sr>=sl&&dp[sta[sr]]<=dp[i]&&a[sta[sr]]<=a[i]) {
sr--;
}
if(sr<sl||dp[sta[sr]]<dp[i]) sta[++sr]=i;
else ef2(sl,sr,dp[i],i);
}
}
void query(int x){
if(x>maxx) puts("Impossible");
else {
int pre=;
for(int i=;i<=n;i++) {
if(dp[i]>=x&&a[i]>pre) {
pre=a[i];
if(x==)
printf("%d",a[i]);
else printf("%d ",a[i]);
x--;
if(!x) break;
}
}
printf("\n");
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
work();
scanf("%d",&m);
for(int i=;i<=m;i++) {
scanf("%d",&x);
query(x);
}
return ;
}

然而正确的nlogn求最长上升序列并不是这么写的,只用一个二分,不过在下并不是很清楚,懒得学以后再说吧。

从LLJ大佬那里学到了用线段树的做法,开一颗权值线段树,从后往前把Dp值存进去,每个点找它后面的最大Dp值来更新,感觉和正常的nlogn的思路可能差不多。

3.

UVA - 12063 Zeros and Ones

二进制数和它们的位模式对于计算机程序员来说总是非常有趣的。 在这个
您需要计算具有以下属性的正数二进制数的问题:
•数字正好是N位宽,它们没有前导零。
•一和零的频率相等。
•数字是K的倍数。
输入
输入文件包含几个测试用例。 输入的第一行为您提供了测试用例数,
T(1≤T≤100)。 那么T测试用例会跟随,每一行都在一行。 每个测试用例的输入包括
的两个整数,N(1≤N≤64)和K(0≤K≤100)。
产量
对于每组输入,首先打印测试用例编号。 然后打印二进制数的数字

谷歌翻译神坑,1和0频率相同翻译成0和0频率相同,喵喵喵?

把Case打成case被坑了一波。。对拍才发现QAQ

最好的做法是往后加0或者1 不用特判,不会炸整,往前加的话就要特判,然后注意开 long long ,要模两次保证不会炸 (LLJ大佬说要开usinged long long ,因为 long long 只到2^64-1,实际这题只到2^63所以不用)

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef unsigned long long LL;
const int maxn=;
const int maxk=;
int T,n,k;
LL dp[maxn][maxn][maxk],ans,ll=;
void work(){
if(!k||n&) {printf("0\n"); return;}
memset(dp,,sizeof(dp));
dp[][][]=;
for(int i=;i<=n;i++)
for(int j=;j<=i;j++)
for(int l=;l<k;l++) {
if(j) dp[i][j][(l+((ll=)<<(i-))%k)%k]+=dp[i-][j-][l];
if(i!=n) dp[i][j][l]+=dp[i-][j][l];
}
ans=;
printf("%llu\n",dp[n][n/][]);
}
int main()
{ scanf("%d",&T);
for(int i=;i<=T;i++){
scanf("%d%d",&n,&k);
printf("Case %d: ",i);
work();
}
return ;
}

这是往后加的版本

    for(int i=;i<n;i++)
for(int j=;j<=i;j++)
for(int l=;l<k;l++) {
dp[i+][j+][((l<<)|)%k]+=dp[i][j][l];
dp[i+][j][(l<<)%k]+=dp[i][j][l];
}

4.

UVA - 1628 Pizza Delivery

我爱记忆化搜索,记忆化搜索最强。

dp[i][j][o][k]表示i到j的订单已处理好,现在在i或者j 还要送k家的最优解

枚举,记忆化

for(int i=;i<l;i++) u=max(u,dfs(i,r,,k-)+e[i]-k*abs(p[i]-p[o==?l:r]));
for(int i=n;i>r;i--) u=max(u,dfs(l,i,,k-)+e[i]-k*abs(p[i]-p[o==?l:r]));

注意这一段先搜两边再中间,可以达到记忆化效果

代码

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=+;
int T,now,dp[maxn][maxn][][maxn],vis[maxn][maxn][][maxn],n,p[maxn],e[maxn],ans;
int dfs(int l,int r,int o,int k) {
if(k==) return ;
if(vis[l][r][o][k]==now) return dp[l][r][o][k];
vis[l][r][o][k]=now;
int &u=dp[l][r][o][k];
u=;
for(int i=;i<l;i++) u=max(u,dfs(i,r,,k-)+e[i]-k*abs(p[i]-p[o==?l:r]));
for(int i=n;i>r;i--) u=max(u,dfs(l,i,,k-)+e[i]-k*abs(p[i]-p[o==?l:r]));
return u;
}
int main()
{
scanf("%d",&T);
for(now=;now<=T;now++) {
ans=;
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&p[i]);
for(int i=;i<=n;i++) scanf("%d",&e[i]);
for(int kk=;kk<=n;kk++)
for(int i=;i<=n;i++)
ans=max(ans,dfs(i,i,,kk-)+e[i]-kk*abs(p[i]));
printf("%d\n",ans);
}
return ;
}

5.BZOJ 1009 [HNOI2008]GT考试

一开始傻逼地kmp直接往前跳一个就停了,后来改了又调了好久发现自己Kmp写错了,贼难受。。

就kmp转移然后矩阵优化。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
int ans,n,m,p,top,a[],nxt[],cnt[],vis[];
struct jz{
int x[][];
friend jz operator *(const jz&l,const jz&r){
jz res;
for(int i=;i<;i++)
for(int j=;j<;j++)
res.x[i][j]=;
for(int i=;i<;i++)
for(int j=;j<;j++) {
for(int k=;k<;k++)
(res.x[i][j]+=(l.x[i][k]*r.x[k][j])%p)%=p;
}
return res;
}
}base,ret,tmp;
void input() {
scanf("%d%d%d",&n,&m,&p);
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) a[++top]=ch-'';
}
int make_nxt(int a[],int *nxt) {
for (int j=,i=;i<=m;i++) {
while (j&&a[j+]!=a[i]) j=nxt[j];
if (a[j+]==a[i]) j++;
nxt[i]=j;
}
}
void ksm(int b){
while(b){
if(b&) ret=ret*base;
base=base*base;
b>>=;
}
}
void work() {
for(int i=;i<m;i++) {
cnt[i]++;
vis[a[i+]]=i+;
if(i+!=m) {base.x[i][i+]++;}
int tp=i;
while(nxt[tp]) {
tp=nxt[tp];
if(vis[a[tp+]]!=i+) {
vis[a[tp+]]=i+;
cnt[i]++;
base.x[i][tp+]++;
}
}
if(vis[a[]]!=i+) {
cnt[i]++;
base.x[i][]++;
}
base.x[i][]+=(-cnt[i]);
}
for(int i=;i<m;i++)
for(int j=;j<m;j++)
if(i==j) ret.x[i][j]=;
ksm(n);
ans=;
for(int i=;i<m;i++)
(ans+=ret.x[][i])%=p;
printf("%d\n",ans);
}
int main()
{
input();
make_nxt(a,nxt);
work();
return ;
}

GT考试

6.BZOJ 1855 [SCOI2010]股票交易

在某位学长的博客里看到这题第一句话是省选怎么会考这么简单的题呢,然后就发现自己不会做。。。

神奇的单调队列优化,可能是我单调队列写得太少了。。

很容易知道状态dp[i][j]表示时间为i手中股票为j的最大收益,初始化为极小值,dp[0][0]=0;

然后转移分三种

不买不卖:dp[i][j]=max(dp[i][j],dp[i-1][j]);

买入:dp[i][j]=max(dp[i][j],dp[i-w-1][j-k]-k*ap[i]);

卖出:dp[i][j]=max(dp[i][j],dp[i-w-1][j+k]+k*bp[i]);

然后我们发现后两个枚举k会超时,就把它优化一下 (其实我也。。比较懵逼)

买入:dp[i][j]=max(dp[i][j],dp[i-w-1][k]-(j-k)*ap[i]);

=max(dp[i][j],(dp[i-w-1][k]+k*ap[i])-j*ap[i]);

卖出:dp[i][j]=max(dp[i][j],dp[i-w-1][k]+(k-j)*bp[i]);

=max(dp[i][j],(dp[i-w-1][k]+k*ap[i])-j*bp[i]);

以买入为例,我们发现 这一部分 dp[i-w-1][k]+k*ap[i] (j-k>0,j-k<as[i])具有单调性,

k>j-as[i] 我们枚举k,然后丢进单调队列, 更新现在的dp[i][k];

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=+;
int ans,n,maxp,w,dp[maxn][maxn];
int ap[maxn],bp[maxn],as[maxn],bs[maxn],que[maxn],ql=,qr;
int main()
{
scanf("%d%d%d",&n,&maxp,&w);
for(int i=;i<=n;i++)
scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
memset(dp,,sizeof(dp));
dp[][]=;
for(int i=;i<=n;i++) {
ql=,qr=;
for(int j=;j<=maxp;j++) {
dp[i][j]=max(dp[i][j],dp[i-][j]);
if(i-w->) {
while(ql<=qr&&que[ql]<j-as[i]) ql++;
while(ql<=qr&&dp[i-w-][que[qr]]+que[qr]*ap[i]-j*ap[i]<=dp[i-w-][j]) qr--;
que[++qr]=j;
if(ql<=qr) dp[i][j]=max(dp[i][j],dp[i-w-][que[ql]]+que[ql]*ap[i]-j*ap[i]);
}
else if(j<=as[i]) dp[i][j]=max(dp[i][j],-ap[i]*j);
}
ql=,qr=;
for(int j=maxp;j>=;j--) {
if(i-w->){
while(ql<=qr&&que[ql]>j+bs[i]) ql++;
while(ql<=qr&&dp[i-w-][que[qr]]+que[qr]*bp[i]-j*bp[i]<=dp[i-w-][j]) qr--;
que[++qr]=j;
if(ql<=qr) dp[i][j]=max(dp[i][j],dp[i-w-][que[ql]]+que[ql]*bp[i]-j*bp[i]);
}
}
}
for(int i=;i<=maxp;i++) ans=max(ans,dp[n][i]);
printf("%d\n",ans);
return ;
}

股票交易

一些DP杂题的更多相关文章

  1. dp杂题(根据个人进度选更)

    ----19.7.30 今天又开了一个新专题,dp杂题,我依旧按照之前一样,这一个专题更在一起,根据个人进度选更题目; dp就是动态规划,本人认为,动态规划的核心就是dp状态的设立以及dp转移方程的推 ...

  2. 贪心/构造/DP 杂题选做Ⅱ

    由于换了台电脑,而我的贪心 & 构造能力依然很拉跨,所以决定再开一个坑( 前传: 贪心/构造/DP 杂题选做 u1s1 我预感还有Ⅲ(欸,这不是我在多项式Ⅱ中说过的原话吗) 24. P5912 ...

  3. 贪心/构造/DP 杂题选做Ⅲ

    颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...

  4. 专题:DP杂题1

    A POJ 1018 Communication System B POJ 1050 To the Max C POJ 1083 Moving Tables D POJ 1125 Stockbroke ...

  5. 【做题记录】DP 杂题

    P2577 [ZJOI2004]午餐 $\texttt{solution}$ 想到贪心: 吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 状态: \(f[i][j]\) 表示前 \(i\ ...

  6. 贪心/构造/DP 杂题选做

    本博客将会收录一些贪心/构造的我认为较有价值的题目,这样可以有效的避免日后碰到 P7115 或者 P7915 这样的题就束手无策进而垫底的情况/dk 某些题目虽然跟贪心关系不大,但是在 CF 上有个 ...

  7. DP杂题2

    1.邦邦的大合唱站队 https://www.luogu.org/problem/show?pid=3694 XY说这是道简单的签到题,然后我大概是普及组都拿不到三等的那种了.. 插入题解.写得太好了 ...

  8. 【模拟8.01】matrix(DP杂题,思维题)

    很神的题,感谢lnc大佬的指点. 先设1-LL[i]统称左区间,RR[i]-m为右区间 用L[i]统计从1-i列,出现的左区间端点的前缀和,R[i]是右区间.... f[i][j]中j表示当前在第i列 ...

  9. 正睿OI DAY3 杂题选讲

    正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n ...

随机推荐

  1. testNG之组测试

    @Test(groups = {""}) 在执行测试用例的时候,往往一个功能依赖多个测试用例,比如流程的测试,那么这个时候就可以用到组测试,把流程涉及到测试用例都分到同一组里,按组 ...

  2. 使用ui给定的字体,通过css引入字体库

    @font-face { font-family: 'LCDMonoNormal'; src: url('../../assets/fonts/LCDM2N__.eot'); src: url('.. ...

  3. 仿flask写的web框架

    某大佬仿flask写的web框架 web_frame.py from werkzeug.local import LocalStack, LocalProxy def get_request_cont ...

  4. 抓包工具tcpdump用法说明--1

    本文目录: 1.1 tcpdump选项 1.2 tcpdump表达式 1.3 tcpdump示例 tcpdump采用命令行方式对接口的数据包进行筛选抓取,其丰富特性表现在灵活的表达式上. 不带任何选项 ...

  5. <读书笔记>《高性能网站建设指南:前端工程师技能精髓》

    只有10-20%的最终用户响应时间花在了下载HTML文档上.其余的80-90%时间花在了下载页面中的所有组件上. 规则1.减少HTTP请求 图片地图:将多个图片合并成一个,而后通过css定位显示不同的 ...

  6. 将libvex移植到Visual Studio编译平台下的经验总结

    1. 两难 将libvex从Linux移植到Windows,移植工作聚集于Cross-Compiler,而不是预料的Cross-Platform. VC++ Compiler到目前为止只支持C89标准 ...

  7. apache2.2.25+tomcat7.0.47集群方案

    因为公司项目在线人数的增加,随着现在硬件成本越来越低,大多数的生产环境内存大多都已经达到 16G,尤其最新的阿里云,客户的机器都是配置超高的java主机,但是Java的运行环境,内存使用有限 ,这样就 ...

  8. 安装项目依赖pipreqs并生成requirements.txt

    安装项目依赖:sudo pip3 install pipreqs 生成依赖文件(requirements.txt):pipreqs ./   # 进入项目目录,在项目文件夹里生成安装依赖文件里的环境: ...

  9. JPA派生标识符2

    @Entity@Table(name = "adam_importfile")@IdClass(BusinessAdviserFileId.class)public class B ...

  10. Spring Boot集成Mybatis双数据源

    这里用到了Spring Boot + Mybatis + DynamicDataSource配置动态双数据源,可以动态切换数据源实现数据库的读写分离. 添加依赖 加入Mybatis启动器,这里添加了D ...