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. python--闭包函数、装饰器

    先来点补充. x= def foo(): print(x) x= foo() 结果: x= def foo(): global x x= print(x) foo() print(x) 结果: x= ...

  2. redis requires Ruby version >= 2.2.2.

    安装RVM 无法在服务器使用curl命令访问https域名,原因是nss版本有点旧了,yum -y update nss更新一下 yum -y update nss 新建rvm-installer.s ...

  3. Delphi RegisterHotKey 设置系统热键

    Symbolic constant name Value (hexadecimal) Keyboard (or mouse) equivalent VK_LBUTTON 01 Left mouse b ...

  4. LOJ 2554 「CTSC2018」青蕈领主——结论(思路)+分治FFT

    题目:https://loj.ac/problem/2554 一个“连续”的区间必然是一个排列.所有 r 不同的.len 最长的“连续”区间只有包含.相离,不会相交,不然整个是一个“连续”区间. 只有 ...

  5. Linux系统Centos查看IP地址,不显示IP地址或者显示127.0.0.1

    1.桌面界面 右上角有个电脑的图标,鼠标悬停会显示no network connect 点击一下图标,选择连接的网络则ok 2.命令行界面 在命令行界面输入 vi  /etc/sysconfig/ne ...

  6. Nginx功能模块汇总

    主要文档 Nginx功能概述.为什么选择Nginx.Nginx安装.常见问题(FAQ).配置符号参考.调试 nginx.优化 Nginx.运行和控制Nginx 核心模块 Nginx事件模块.Nginx ...

  7. python四种方法实现去除列表中的重复元素

    转载:https://blog.csdn.net/together_cz/article/details/76201975 def func1(one_list): ''''' 使用集合,个人最常用 ...

  8. windows10下Mysql5.7安装指南

    背景 值此国庆70周年之际,为了发扬广大国内软件开发行业,我决定使用MySQL5.7. 呸!实际情况是公司的项目用的是Mysql5.7,但是正式服务器在国外,而且测试服务器也是在国外,关键问题是我这个 ...

  9. 67、saleforce的object的describe方法使用

    使用Schema类的describesSObjects方法获取描述sObject结果.使用此方法可以通过sObject类型名称描述一个或者多个sObject描述信息. //sObject types ...

  10. 如何在vim中同时编辑多个文件

    参考:http://stackoverflow.com/a/53668/941650 Why not use tabs (introduced in Vim 7)? You can switch be ...