『一本通』区间DP

石子合并

 1 #include<bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 int n,sm[505][505],bg[505][505],sum[505];
 5 inline int read() {
 6     int x=0,f=1; char c=getchar();
 7     while(c<‘0‘||c>‘9‘) {if(c==‘-‘)f=-1; c=getchar();}
 8     while(c>=‘0‘&&c<=‘9‘) x=(x<<3)+(x<<1)+c-‘0‘,c=getchar();
 9     return x*f;
10 }
11
12 int main() {
13     n=read();
14     for(int i=1;i<=n;i++) sum[i]=read(),sum[i+n]=sum[i];
15     memset(sm,INF,sizeof(sm));
16     for(int i=1;i<=2*n;i++) sm[i][i]=0,sum[i]+=sum[i-1];
17     for(int i=2;i<=n;i++)
18      for(int l=1;l+i-1<=2*n;l++) {
19          int r=l+i-1;
20          for(int k=l;k<r;k++) {
21              sm[l][r]=min(sm[l][r],sm[l][k]+sm[k+1][r]);
22              bg[l][r]=max(bg[l][r],bg[l][k]+bg[k+1][r]);
23          }
24          sm[l][r]+=sum[r]-sum[l-1];
25          bg[l][r]+=sum[r]-sum[l-1];
26      }
27     int minn=INF,maxx=0;
28     for(int i=1;i<=n;i++) {
29         maxx=max(maxx,bg[i][i+n-1]);
30         minn=min(minn,sm[i][i+n-1]);
31     }
32     printf("%d\n%d",minn,maxx);
33 }
34 /*
35 区间DP (环形处理+前缀和)
36 sm[l][r]为合并 l~r 堆石子的得分总和最小值
37 bg[l][r]为合并 l~r 堆石子的得分总和最大值
38 枚举合并断点 k
39 得 sm/bg[l][r]=min/max(sm/bg[l][r],sm/bg[l][k]+sm/bg[k+1][r])
40 最后加上这次合并获得的得分 sum[r]-sum[l-1]
41 */

能量项链

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,f[1005][1005],a[1005];
 4 inline int read() {
 5     int x=0,f=1; char c=getchar();
 6     while(c<‘0‘||c>‘9‘) {if(c==‘-‘)f=-1; c=getchar();}
 7     while(c>=‘0‘&&c<=‘9‘) x=(x<<3)+(x<<1)+c-‘0‘,c=getchar();
 8     return x*f;
 9 }
10
11 int main() {
12     n=read();
13     for(int i=1;i<=n;i++) a[i]=read(),a[i+n]=a[i];
14     for(int i=3;i<=n+1;i++)
15      for(int l=1;l+i-1<=2*n;l++) {
16          int r=l+i-1;
17          for(int k=l+1;k<r;k++)
18           f[l][r]=max(f[l][r],f[l][k]+f[k][r]+a[l]*a[r]*a[k]);
19      }
20     int ans=0;
21     for(int i=1;i<=n;i++) ans=max(ans,f[i][i+n]);
22     printf("%d",ans);
23 }
24 /*
25 区间DP
26 f[i][j]:将 i~j-1 的珠子聚合所能释放的最大能量
27 注意循环的边界。
28 */ 

矩阵取数

 1 #include<bits/stdc++.h>
 2 #define int __int128 //拯救你的高精度
 3 using namespace std;
 4 int n,m,ans,a[105],f[105][105];
 5 inline int read() {
 6     int x=0,f=1; char c=getchar();
 7     while(c<‘0‘||c>‘9‘) {if(c==‘-‘)f=-1; c=getchar();}
 8     while(c>=‘0‘&&c<=‘9‘) x=(x<<3)+(x<<1)+c-‘0‘,c=getchar();
 9     return x*f;
10 }
11 void write(int x) {
12     if(x>9) write(x/10);
13     putchar(x%10+‘0‘);
14 }
15
16 main() {
17     n=read(),m=read();
18     for(int k=1;k<=n;k++) {
19         for(int i=1;i<=m;i++) a[i]=read()*2,f[i][i]=a[i];
20         for(int i=2;i<=m;i++)
21          for(int l=1;l+i-1<=m;l++) {
22              int r=l+i-1;
23              f[l][r]=max(a[l]+f[l+1][r]*2,a[r]+f[l][r-1]*2);
24          }
25         ans+=f[1][m];
26     }
27     write(ans);
28 }
29 /*
30 区间DP
31 每一行取数不会影响到其它行,只要保证每一行得分最大即可(最优子结构)
32 设f[i][j]表示取区间[i][j]的最大得分。
33 转移方程:f[l][r]=max(a[l]+f[l+1][r]*2,a[r]+f[l][r-1]*2)
34 细节(输入时将a[i]*2)
35 */ 

括号配对

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char a[105];
 4 int len,f[105][105];
 5 int main() {
 6     scanf("%s",a+1); len=strlen(a+1);
 7     for(int l=len;l>0;l--)
 8      for(int r=l+1;r<=len;r++) {
 9         if((a[l]==‘(‘&&a[r]==‘)‘)||(a[l]==‘[‘&&a[r]==‘]‘)) f[l][r]=2+f[l+1][r-1];
10         for(int k=l;k<r;k++) f[l][r]=max(f[l][r],f[l][k]+f[k+1][r]);
11      }
12     printf("%d",len-f[1][len]);
13 }
14 /*
15 区间DP
16 题目要求添加的括号数,只需将括号总数减去已匹配的括号数(求出未匹配的括号数)
17 未匹配的括号数=需添加的括号数
18 所以我们求最多能匹配多少个括号(区间DP:判断匹配情况+枚举断点)
19 注意:第一层循环(枚举L)应为LEN~1(方程式要从后面的情况转移)
20 */ 

凸多边形的划分

 1 #include<bits/stdc++.h>
 2 #define int __int128
 3 using namespace std;
 4 int n,a[55],f[55][55];
 5 void print(int x) {
 6     if(x<0) putchar(‘-‘),x=-x;
 7     if(x>9) print(x/10);
 8     putchar(x%10+‘0‘);
 9 }
10
11 main() {
12     scanf("%d",&n);
13     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
14     for(int i=3;i<=n;i++)
15      for(int l=1;l+i-1<=n;l++) {
16         int r=l+i-1; f[l][r]=1e30;
17         for(int k=l+1;k<r;k++)
18          f[l][r]=min(f[l][r],f[l][k]+f[k][r]+a[l]*a[r]*a[k]);
19      }
20     print(f[1][n]);
21 }
22 //区间DP(画图理解)

原文地址:https://www.cnblogs.com/qq8260573/p/10145477.html

时间: 2024-08-01 15:04:01

『一本通』区间DP的相关文章

『字符合并 区间dp 状压dp』

字符合并 Description 有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数.得到的新字符和分数由这 k 个字符确定.你需要求出你能获得的最大分数. Input Format 第一行两个整数n,k.接下来一行长度为n的01串,表示初始串. 接下来2^k行,每行一个字符ci和一个整数wi,ci表示长度为k的01串连成二进制后按从小到大顺序得到的第i种合并方案得到的新字符,wi表示对应的第i种方案对应获得的分数. 1<=n<=300,0<

『一本通』二分与三分

愤怒的牛 1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,ans,a[100005]; 4 5 int check(int x) { 6 int cnt=1,lst=a[1]; 7 for(int i=2;i<=n;i++) 8 if(a[i]-lst>=x) cnt++,lst=a[i]; 9 return cnt; 10 } 11 12 int main() { 13 scanf("%d%d&quo

『一本通』广搜的优化技巧

Knight Moves 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int dx[9]={2,2,1,1,-1,-1,-2,-2},dy[9]={-1,1,-2,2,-2,2,-1,1}; 4 int n,L,step[305][305]; 5 struct node{int x,y;}b,e; 6 queue<node>q; 7 bool check(int x,int y) {return x>=0&

『一本通』哈希和哈希表

Oulipo 1 #include<bits/stdc++.h> 2 #define N 1000000+5 3 using namespace std; 4 typedef unsigned long long ULL; 5 const int b=55; 6 ULL n,m,s,ans,p[N],sum[N]; 7 char s1[N],s2[N]; 8 9 int main() { 10 scanf("%s",s1+1),scanf("%s",s2

『一本通』差分约束系统

Intervals 设$s[k]$表示$0$~$k$之间最少选出多少个整数. 由题得$s[b_i]-s[a_i-1]\ge c_i$,$0\le s[k+1]-s[k] \le 1$ . 根据关系式连边,$SPFA$ 跑一遍 最长路 即可. #include<bits/stdc++.h> using namespace std; const int N=5e4+5; int n,cnt,Min,Max,fro[N],dis[N]; bool vis[N]; struct edge{int to

『转』数学专辑

1.burnside定理,polya计数法 这个大家可以看brudildi的<组合数学>,那本书的这一章写的很详细也很容易理解.最好能完全看懂了,理解了再去做题,不要只记个公式. *简单题:(直接用套公式就可以了) pku2409 Let it Bead   http://acm.pku.edu.cn/JudgeOnline/problem?id=2409 pku2154 Color http://acm.pku.edu.cn/JudgeOnline/problem?id=2154 pku12

uva 10003 Cutting Sticks 简单区间dp

// uva 10003 Cutting Sticks 区间dp // 经典的区间dp // dp(i,j)表示切割小木棍i-j所需要的最小花费 // 则状态转移为dp(i,j) = min{dp(i,k) + dp(k,j) + a[j]-a[i]) // 其中k>i && k<j // a[j] - a[i] 为第一刀切割的代价 // a[0] = 0,a[n+1] = L; // dp数组初始化的时候dp[i][i+1]的值为 0,这表示 // 每一段都已经是切割了的,不

『ENGLISH』

以A字母开头的词汇 英文 中文 abstract module 抽象模组 access 访问.存取 access control 存取控制 access control information 存取控制资讯 access mechanism 存取机制 access rights 存取权限 accessibility 无障碍性 accessibility information 无障碍网页资讯 accessibility problem 无障碍网页问题 accessible 无障碍的 access

黑书例题 Fight Club 区间DP

题目可以在bnuoj.soj等OJ上找到. 题意: 不超过40个人站成一圈,只能和两边的人对战.给出任意两人对战的输赢,对于每一个人,输出是否可能是最后的胜者. 分析: 首先序列扩展成2倍,破环成链. dp[i][j]表示i和j能够相遇对打,那么dp[i][i+n]为真代表可以成为最后胜者. 枚举中间的k,若i和j都能和k相遇,且i和j至少一人能打赢k,那么i和j可以相遇. 复杂度o(n^3) 1 #include<cstdio> 2 #include<cstring> 3 usi