282. 石子合并 - AcWing题库
https://www.acwing.com/problem/content/284/



- #include
- using namespace std;
- const int N=410,INF=0x3f3f3f3f;
- int f[N][N];
- int g[N][N];
- int a[N];
- int s[N];
- int main()
- {
- int n;
- cin>>n;
- memset(f,INF,sizeof f);
- memset(g,-INF,sizeof g);
- for(int i=1;i<=n;i++)
- {
- cin>>a[i];
- a[i+n]=a[i];
- }
- for(int i=1;i<=n*2;i++)
- {
- s[i]=a[i]+s[i-1];
- f[i][i]=0;
- g[i][i]=0;
- }
-
- for(int len=2;len<=n;len++)
- for(int i=1;i+len-1<=n*2;i++)
- {
- int l=i,r=len+i-1;
-
- for(int k=l;k
- {
- f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
- g[l][r]=max(g[l][r],g[l][k]+g[k+1][r]+s[r]-s[l-1]);
- }
- }
- int minv=INF,maxv=-INF;
- for(int i=1;i<=n;i++)
- {
- minv=min(minv,f[i][i+n-1]);
- maxv=max(maxv,g[i][i+n-1]);
- }
- cout<
- }
能量项链【区间DP】
题目 能量项链
https://www.acwing.com/problem/content/description/322/

- #include
- using namespace std;
- typedef long long ll;
- const int N=210;
- ll f[N][N];
- ll a[N];
- int main()
- {
- int n;
- cin>>n;
- for(int i=1;i<=n;i++)
- {
- cin>>a[i];
- a[i+n]=a[i];
- }
- for(int len=3;len<=n+1;len++)
- for(int l=1;len+l-1<=2*n;l++)
- {
- int r=l+len-1;
- for(int k=l+1;k
- f[l][r]=max(f[l][r],f[l][k]+f[k][r]+a[l]*a[k]*a[r]);
- }
-
- ll res=0;
- for(int i=1;i<=n;i++)
- res=max(res,f[i][i+n]);
- cout<
- }

- #include
- using namespace std;
- typedef long long ll;
- const int N=35;
- int w[N],f[N][N],g[N][N];//f记录[l,r]区间的分数,g记录[l,r]的根节点
- void dfs(int l,int r)//前序遍历是根左右
- {
- if(l>r) return ;
- int root=g[l][r];//根
- cout<
' '; - dfs(l,root-1);//左子树
- dfs(root+1,r);//右子树
- }
- int main()
- {
- int n;
- cin>>n;
- for(int i=1;i<=n;i++) cin>>w[i];
- memset(f,-0x3f,sizeof f); //因为要求最大值,则初始化为负无穷
- for(int len=1;len<=n;len++) //枚举[l,r]的长度
- for(int l=1;l+len-1<=n;l++)//枚举l
- {
- int r=l+len-1;
- if(len==1) //假如只有自己,则分数是自己,根也是自己
- {
- f[l][r]=w[l];
- g[l][r]=l;
- }
- else
- {
- for(int k=l;k<=r;k++)//枚举[l,r]之间的根节点
- {
- int left = k==l ? 1 : f[l][k-1];//假如k是等于l,说明l到k没有左子树,则分数为1
- int right = k==r ? 1 : f[k+1][r];//假如k是等于r,说明l到k没有右子树,则分数为1
- int socre=left*right+w[k];//算一下分数
- if(f[l][r]
//假如可以更新最大值 - {
- f[l][r]=score;
- g[l][r]=k;
- }//更新分数,还有[l,r]的根节点k
- }
- }
- }
- cout<
1][n]<//输出[l,r]区间的二叉树的分数 - dfs(1,n);//前序遍历求根节点
- return 0;
- }
凸多边形的划分【区间DP+高精度=缝合怪】
由于这题每个w[i]都是10^9,则三个乘以的话就10^27,则要自己写个高精度加法与乘法
- //没加高精度的模板,过不了
- #include
- using namespace std;
- const int N=210;
- int w[N],f[N][N];
- int main()
- {
- int n;
- cin>>n;
- for(int i=1;i<=n;i++) cin>>w[i];
- for(int len=3;len<=n;len++)//枚举l到r的长度
- for(int l=1;l+len-1<=n;l++)
- {
- int r=len+l-1;
- f[l][r]=0x3f3f3f3f;//因为要求最小值,所以初始化为正无穷
- for(int k=l+1;k
- f[l][r]=min(f[l][r],f[l][k]+f[k][r]+w[l]*w[k]*w[r]);
- }
- cout<
1][n]< - return 0;
- }
高精度 优化
- #include
- using namespace std;
- typedef long long ll;
- const int N=55,M=35;
- ll w[N],f[N][N][M];
- void add(ll a[],ll b[])//高精度加法
- {
- static ll c[M];
- memset(c,0,sizeof c);
- ll t=0;
- for(int i=0;i
- {
- t+=a[i]+b[i];
- c[i]=t%10;
- t/=10;
- }
- memcpy(a,c,sizeof c);
- }
- void mul(ll a[],ll b)//高精度乘法
- {
- static ll c[M];
- memset(c,0,sizeof c);
- ll t=0;
- for(int i=0;i
- {
- t+=a[i]*b;
- c[i]=t%10;
- t/=10;
- }
- memcpy(a,c,sizeof c);
- }
- bool cmp(ll a[],ll b[])//比较两个数的大小
- {
- for(int i=M-1;i>=0;i--)
- if(a[i]>b[i]) return true;
- else if(a[i]return false;
- return false;
- }
- void print(ll a[])//用来输出答案
- {
- int k=M-1;
- while(k&&!a[k]) k--;
- cout<
- }
- int main()
- {
- int n;
- cin>>n;
- for(int i=1;i<=n;i++) cin>>w[i];
- ll temp[M];
- for(int len=3;len<=n;len++)//枚举l到r的长度
- for(int l=1;l+len-1<=n;l++)
- {
- int r=len+l-1;
- //f[l][r]=0x3f3f3f3f;
- f[l][r][M-1]=1;//因为要求最小值,所以初始化为正无穷,最高位是1,说明1e34,已经很大了
- for(int k=l+1;k
- {
- // f[l][r]=min(f[l][r],f[l][k]+f[k][r]+w[l]*w[k]*w[r]);
- memset(temp,0,sizeof temp);//清空上一次的数组
- temp[0]=w[l];
- mul(temp,w[k]);
- mul(temp,w[r]);
- add(temp,f[l][k]);
- add(temp,f[k][r]);
- if(cmp(f[l][r],temp))
- memcpy(f[l][r],temp,sizeof temp);
- }
- }
- print(f[1][n]);
- return 0;
- }
加分二叉树
题目
http://ybt.ssoier.cn:8088/problem_show.php?pid=1833
- #include
- using namespace std;
- const int N=35;
- int f[N][N],g[N][N];
- int w[N];
- int n;
- void dfs(int l,int r)
- {
- if(l>r)return;
- int root=g[l][r];
- cout<
" "; - dfs(l,root-1);
- dfs(root+1,r);
- }
- int main()
- {
- cin>>n;
- for(int i=1;i<=n;i++)
- cin>>w[i];
- for(int len=1;len<=n;len++)
- for(int l=1;l+len-1<=n;l++)
- {
- int r=l+len-1;
- if(len==1)
- {
- f[l][r]=w[l];
- g[l][r]=l;
- }
- else
- {
- for(int k=l;k<=r;k++)
- {
- int left = k==l ? 1 : f[l][k-1];
- int right = k==r ? 1 :f[k+1][r];
- int sorce = w[k] + left * right;
- if(f[l][r]
- {
- f[l][r]=sorce;
- g[l][r]=k;
- }
- }
- }
- }
- cout<
1][n]< - dfs(1,n);
- }
棋盘分割
题目 棋盘分割
https://www.acwing.com/problem/content/description/323/
解析
https://www.acwing.com/solution/content/62836/

横着切:

竖着切:

- #include
- using namespace std;
- const int N=15,M=9;
- const double INF=1e9;
- int s[M][M];//二维前缀和
- double f[M][M][M][M][N];
- double X;//平均数
- int n;
- double get(int x1,int y1,int x2,int y2)//求子矩阵的方差
- {
- double sum=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]-X;//求方差
- return sum*sum/n;
- }
- double dp(int x1,int y1,int x2,int y2,int k)//记忆化搜索
- {
- double &v=f[x1][y1][x2][y2][k];
- if(v>=0) return v;//假如已经处理过直接返回他的值
- if(k==1) return v=get(x1,y1,x2,y2);//假如切割是一次,则就是最后一块子矩阵,则直接求他的值,不用再切割
- v=INF;//因为要求最小值,初始化为正无穷
- for(int i=x1;i
//枚举横向切割 - {
- v=min(v,dp(x1,y1,i,y2,k-1)+get(i+1,y1,x2,y2));//取上面的部分
- v=min(v,dp(i+1,y1,x2,y2,k-1)+get(x1,y1,i,y2));//取下面的部分
- }
- for(int i=y1;i
//枚举纵向切割 - {
- v=min(v,dp(x1,y1,x2,i,k-1)+get(x1,i+1,x2,y2));//取左边部分
- v=min(v,dp(x1,i+1,x2,y2,k-1)+get(x1,y1,x2,i));//取右边部分
- }
- return v;
-
- }
- int main()
- {
- cin>>n;
- for(int i=1;i<=8;i++)
- for(int j=1;j<=8;j++)
- {
- cin>>s[i][j];
- s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];//二维前缀和
- }
- memset(f,-1,sizeof f);//初始化为-1,便于记忆化搜索
- X=(double)s[8][8]/n;//求平均数
- printf("%.3lf\n",sqrt(dp(1,1,8,8,n)));//输出根号方差,即均方差
- return 0;
- }
-
相关阅读:
解读《超越智商》
疑惑与解答
开快递驿站能赚钱么?去掉成本,一个月能赚多少钱?
Python+Requests+Pytest+YAML+Allure实现接口自动化
rust输入输出
基于JAVA评标专家管理信息系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
webRTC H265浏览器播放器+metaRTC推流实现webRTC H265解决方案
CEF内核浏览器安装、解决过滤图片、链接弹窗问题
codeforces每日5题(均1500)-第二十一天
double 和 float 的区别
-
原文地址:https://blog.csdn.net/m0_64378422/article/details/127817486