YBT 5.1 区间类动态规划
题解在代码中
石子合并[loj 10147]
/*
dp[i][j]=max or min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1])
i<=k<j
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int a[],n,dp_minn[][],dp_maxn[][],sum[];
int main()
{
memset(dp_minn,,sizeof(dp_minn));
n=read();
for(int i=;i<=n;i++)
{
dp_minn[i][i]=dp_minn[i+n][i+n]=;
a[i]=read(),a[i+n]=a[i];
}
for(int i=;i<=*n;i++) sum[i]=sum[i-]+a[i];
for(int t=;t<=n;t++)
for(int i=;i<=*n&&i+t-<=*n;i++)
{
int j=i+t-; for(int k=i;k<j;k++)
{
dp_maxn[i][j]=max(dp_maxn[i][j],dp_maxn[i][k]+dp_maxn[k+][j]+sum[j]-sum[i-]);
dp_minn[i][j]=min(dp_minn[i][j],dp_minn[i][k]+dp_minn[k+][j]+sum[j]-sum[i-]);
}//cout<<i<<" "<<j<<" "<<dp_minn[i][j]<<endl;
}
int maxn=,minn=<<-;
for(int i=;i<=n;i++) maxn=max(maxn,dp_maxn[i][i+n-]),minn=min(minn,dp_minn[i][i+n-]);
cout<<minn<<endl<<maxn;
}
能量项链[loj 10148]
/*
为了好想 记录每一的head和tail
so dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+head[i]*tail[k]*tail[j])
i<=k<j
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
long long dp[][],a[],h[],t[];
int main()
{
long long n=read();
for(long long i=;i<=n;i++) a[i]=read(),a[i+n]=a[i];
for(long long i=;i<*n;i++) h[i]=a[i],t[i]=a[i+];
// for(int i=1;i<2*n;i++) cout<<h[i]<<" "<<t[i]<<endl;
for(long long tt=;tt<n;tt++)
for(long long i=;i<=*n&&i+tt<=*n;i++)
{
long long j=i+tt;
// cout<<i<<" "<<j<<endl;
for(long long k=i;k<j;k++) dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+][j]+h[i]*t[k]*t[j]);
}
long long maxn=;
for(long long i=;i<=n;i++) maxn=max(maxn,dp[i][i+n-]);
cout<<maxn;
}
/*
7
23 17 212 113 71 301 33
31182687
*/
凸多边形的划分[loj 10149]
/*
高精度或__int128
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[k]*a[j])
dp[i][j][0]存位数
其他四个数一个int
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return ans*f;
}
long long n,a[];
long long dp[][][];
long long s1[],s2[],s3[];
void print()
{
cout<<dp[][n][dp[][n][]];
for(long long i=dp[][n][]-;i>=;i--)
{
cout<<dp[][n][i]/;
cout<<dp[][n][i]/%;
cout<<dp[][n][i]/%;
cout<<dp[][n][i]%;
}
}
void mark(long long c[])
{
for(long long i=;i<=c[];i++)
{
c[i+]+=c[i]/;
c[i]%=;
}
while(c[c[]+]!=)
{
c[]++;
c[c[]+]=c[c[]]/;
c[c[]]%=;
}
}
void mul(long long a1,long long a2,long long a3,long long c[])
{
c[]=c[]=;
for(long long i=;i<=c[];i++) c[i]*=a1;
mark(c);
for(long long i=;i<=c[];i++) c[i]*=a2;
mark(c);
for(long long i=;i<=c[];i++) c[i]*=a3;
mark(c);
}
void add(long long a[],long long b[],long long c[])
{
if(a[]>b[]) c[]=a[];
else c[]=b[];
for(long long i=;i<=c[];i++) c[i]=a[i]+b[i];
mark(c);
}
long long compare(long long a[],long long b[])
{
if(a[]>b[]) return ;
if(a[]<b[]) return ;
for(long long i=a[];i>=;i--)
{
if(a[i]<b[i]) return ;
else if(a[i]>b[i]) return ;
}
return ;
}
int main()
{
n=read();
for(long long i=;i<=n;i++) a[i]=read();
for(long long t=;t<=n-;t++)
{
for(long long i=;i+t<=n;i++)
{
long long j=i+t;
dp[i][j][]=;
for(long long k=i+;k<=j-;k++)
{
memset(s1,,sizeof(s1));
memset(s2,,sizeof(s2));
memset(s3,,sizeof(s3));
mul(a[i],a[k],a[j],s1);
add(dp[i][k],dp[k][j],s2);
add(s1,s2,s3);
if(compare(dp[i][j],s3))
memcpy(dp[i][j],s3,sizeof(s3));
}
}
}
print();
}
括号配对[loj 10150]
/*
dp[i][j]表示在[i,j]中至少需要添加的数量
1. (i==[ j==] ) or(i==( j==)) dp[i][j]=min(dp[i][j],dp[i+1][j-1]
2. i==( or i==[ dp[i][j]=min(dp[i][j],dp[i+1][j])
3. j==) or j==] dp[i][j]=min(dp[i][j],dp[i][j-1])
4. dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]) (i<=k<j) 初始化时dp[i][j]=inf (i<=j) dp[i][i]=1;(1<=i<=n)
想一想为什么
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
char str[];
int a[];
int dp[][],inf=<<-;
int main()
{
// memset(dp,127,sizeof(dp)); scanf("%s",str+);
int len=strlen(str+);
for(int i=;i<=len;i++)
for(int j=i;j<=len;j++) dp[i][j]=inf;
for(int i=;i<=len;i++)
{
dp[i][i]=;
if(str[i]=='(') a[i]=;
if(str[i]==')') a[i]=;
if(str[i]=='[') a[i]=;
if(str[i]==']') a[i]=;
}
for(int t=;t<len;t++)
{
for(int i=;i+t<=len;i++)
{
int j=i+t;
if((a[i]==&&a[j]==)||(a[i]==&&a[j]==)) dp[i][j]=min(dp[i][j],dp[i+][j-]);
if(a[i]==||a[i]==) dp[i][j]=min(dp[i][j],dp[i+][j]+);
if(a[j]==||a[j]==) dp[i][j]=min(dp[i][j],dp[i][j-]+);
for(int k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+][j]);
// cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
}
}
cout<<dp[][len];
}
分离与合体[loj 10151]
/*
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+(a[i]+a[j])*a[k])
i<=k<j 用last记录
bfs保证了一分为二,二分为四的输出
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
int n,a[],dp[][],last[][];
void bfs()
{
queue< pair <int,int > > que;
que.push(make_pair(,n));
while(!que.empty())
{
pair<int,int> s=que.front();
que.pop();
if(s.first==s.second) continue;
cout<<last[s.first][s.second]<<" ";
que.push(make_pair(s.first,last[s.first][s.second]));
que.push(make_pair(last[s.first][s.second]+,s.second));
}
}
int main()
{
n=read();
for(int i=;i<=n;i++) a[i]=read();
for(int t=;t<n;t++)
for(int i=;i+t<=n;i++)
{
int j=i+t;
for(int k=j-;k>=i;k--)
{
int t=dp[i][k]+dp[k+][j]+(a[i]+a[j])*a[k];
if(t>=dp[i][j])
{
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+][j]+(a[i]+a[j])*a[k]);
last[i][j]=k;
}
}
}
cout<<dp[][n]<<endl;
bfs();
return ;
}
矩阵取数游戏[loj 10152]
/*
一行一行处理
dp[i][j]表示变到 i,j时的最大分数
dp[i][j]=max(dp[i][j],dp[i-1][j]*a[i-1]^pow(2,n+i-j-1),dp[i][j+1]*a[j+1]^pow(2,n+i-j-1))
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline long long read()
{
long long f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
} __int128 dp[][],ans,sry[];
long long n,m,a[];
void print(__int128 x)
{
if(x==) return;
else if(x!=) print(x/);
putchar(x%+'');
}
int main()
{
sry[]=;
for(int i=;i<=;i++) sry[i]=sry[i-]*;
n=read(),m=read();
for(long long i=;i<=n;i++)
{
for(long long j=;j<=m;j++) a[j]=read();
memset(dp,,sizeof(dp));
for(long long i=;i<=m;i++)
for(long long j=m;j>=i;j--)
dp[i][j]=max(dp[i-][j]+a[i-]*sry[m-j+i-],dp[i][j+]+a[j+]*sry[m-j+i-]);
__int128 maxn=-;
for(long long i=;i<=m;i++) maxn=max(maxn,dp[i][i]+a[i]*sry[m]);
ans+=maxn;
}
if(ans==)
{
cout<<;return ;}
print(ans);
}
YBT 5.1 区间类动态规划的更多相关文章
- hdoj1584 蜘蛛牌 (区间型动态规划)
hdoj1584 分析: f[i][j] 表示 把一串牌 牌 i 到 j 摞为一摞时 所花费最少的步数. d[i][j] 表示把牌 i 挪到牌 j 上时需要走的步数(最初给的状态). 以一串牌 3~8 ...
- Codeforces Gym100543L Outer space invaders 区间dp 动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100543L.html 题目传送门 - CF-Gym100543L 题意 $T$ 组数据. 有 $n ...
- poj3190区间类贪心+优先队列
题意:每个奶牛产奶的时间为A到B,每个奶牛产奶时要占用一间房子,问n头奶牛产奶共需要多少房子,并输出每头奶牛用哪间房子 分析:这题就是一个裸的贪心,将奶牛按开始时间进行排序即可,但考虑一下数据范围,我 ...
- YBT 5.4 状态压缩动态规划
#loj 10170. 「一本通 5.4 例 1」骑士 看数据范围n<=10,所以不是搜索就是状压dp,又因为搜索会超时所以用dp dp[i][k][j]表示现已经放到第i行,前面共有k个,这一 ...
- C# 通用区间类
public class Zone<T> where T : IComparable<T> { /// <summary> /// .ctor /// </s ...
- P3622 [APIO2007]【一本通提高状态压缩类动态规划】动物园
广告 绿树公司 - 官方网站:https://wangping-lvshu.github.io/LvshuNew/ 绿树智能 - 官方网站:https://wangping-lvshu.github. ...
- 区间DP(超详细!!!)
一.问题 给定长为n的序列a[i],每次可以将连续一段回文序列消去,消去后左右两边会接到一起,求最少消几次能消完整个序列,n≤500. f[i][j]表示消去区间[i,j]需要的最少次数. 则; 若a ...
- 区间DP小结 及例题分析:P1880 [NOI1995]石子合并,P1063 能量项链
区间类动态规划 一.基本概念 区间类动态规划是线性动态规划的拓展,它在分阶段划分问题时,与阶段中元素出现的顺序和由前一阶段的那些元素合并而来由很大的关系.例如状态f [ i ][ j ],它表示以已合 ...
- 区间DP的瞎扯淡
写在前面连个引言都不加就直接开1. 区间DP状态常见模板: f[i][j]常常表示第i个到第j个这个区间内达到题目要求,所需要的最小值(最大值) 如: 1. [石子合并](https://www.lu ...
随机推荐
- 微信小程序—day04
元素水平+垂直居中 昨天的用户页的用户头像,是根据已知的像素大小,设置固定的值,达到居中的效果. 今日切换机型进行适配,发现对不同尺寸大小的屏幕不匹配.所以对wxss进行修改,真正达到水平+垂直居中. ...
- 使用postman实现半自动化
前些日子项目要上一个活动,其中有一个功能是幸运大转盘,用户可以随机抽奖,奖品有多种满减券及多种商品,但是奖品都是有抽中概率的,且有的商品还设置有库存,所以测试点便是测试抽奖的概率和库存.接下来拆分一下 ...
- (Python爬虫02) 制定爬虫的学习计划了
公司清退是件很让人郁闷的事情,精,气,神 都会受到影响.焦虑的心态,涣散的眼神, 无所适从的若无其事,人周茶凉的快速交接,各种担忧....平静的面孔波涛汹涌的心.... 认识聊天中满满的套路...还有 ...
- Firefox-css-hack
先记下:之后研究.试了一下,新版本FF-32.0效果不错,低版本还没测试. @-moz-document url-prefix() { .container { ... }}
- aishell数据处理为thchs30格式
目录 aishell数据转换格式 aishell数据转化方法 aishell数据格式对于用神经网络处理数据的同学来说比较不友善,因为他只有文字转录和音素级别的转录,并没有拼音的转录. 而thchs30 ...
- TensorFlow | ReluGrad input is not finite. Tensor had NaN values
问题的出现 Question 这个问题是我基于TensorFlow使用CNN训练MNIST数据集的时候遇到的.关键的相关代码是以下这部分: cross_entropy = -tf.reduce_sum ...
- 八:The YARN Timeline Server
一.Overview 介绍 yarn timeline server用于存储和检查应用程序过去和现在的信息(比如job history server).有两个功能: 1.Persisting ...
- android入门 — AlertDialog对话框
常见的对话框主要分为消息提示对话框.确认对话框.列表对话框.单选对话框.多选对话框和自定义对话框. 对话框可以阻碍当前的UI线程,常用于退出确认等方面. 在这里主要的步骤可以总结为: 1.创建Aler ...
- lintcode-196-寻找缺失的数
196-寻找缺失的数 给出一个包含 0 .. N 中 N 个数的序列,找出0 .. N 中没有出现在序列中的那个数. 样例 N = 4 且序列为 [0, 1, 3] 时,缺失的数为2. 挑战 在数组上 ...
- iOS开发跳转指定页面
for (UIViewController *VC in self.navigationController.viewControllers) { if ([VC isKindOfClass:[Car ...