首页 > 其他分享 >区间DP

区间DP

时间:2023-04-15 12:03:01浏览次数:25  
标签:std include int cin 区间 using main DP

区间DP

区间类动态规划是线性动态规划的扩展,它在分阶段地划分问题时,与阶段中元素出现的顺序和由前一阶段的哪些元素合并而来有很大的关系。

例题

石子合并 洛谷1880

#include<bits/stdc++.h>
using namespace std;
int n,i,j,k,l,ma,mi,a[205],b[205],f[205][205],g[205][205];
int main()
{
	cin>>n;
	for (i=1;i<=n;i++)
	{
		cin>>a[i];
		b[i]=b[i-1]+a[i];
	}
	for (i=n+1;i<=2*n;i++)
		b[i]=b[i-1]+a[i-n];
	mi=INT_MAX;
	for (l=1;l<=n;l++)
	{
		memset(g,64,sizeof(g));
		for (i=1;i<=n*2;i++)
			g[i][i]=0;
		memset(f,0,sizeof(f));
		for (i=2;i<=n;i++)
			for (j=l;j<=n-i+l;j++)
				for (k=j;k<=j+i-2;k++)
				{
					f[j][i+j-1]=max(f[j][i+j-1],f[j][k]+f[k+1][i+j-1]+b[i+j-1]-b[j-1]);
					g[j][i+j-1]=min(g[j][i+j-1],g[j][k]+g[k+1][i+j-1]+b[i+j-1]-b[j-1]);
				}
		ma=max(ma,f[l][n+l-1]);
		mi=min(mi,g[l][n+l-1]);
	}
	cout<<mi<<'\n'<<ma<<'\n';
}

关路灯 洛谷1220

#include<bits/stdc++.h>
using namespace std;
int n,m,i,j,a[100],b[100],c[100],f[100][100][2];
int main()
{
	cin>>n>>m;
	for (i=1;i<=n;i++)
	{
		cin>>a[i]>>b[i];
		c[i]=c[i-1]+b[i];
	}
	memset(f,127,sizeof(f));
	f[m][m][0]=0;f[m][m][1]=0;
	for (i=2;i<=n;i++)
	{
		for (j=1;j<=n-i+1;j++)
		{
			f[j][j+i-1][0]=min(f[j+1][j+i-1][1]+(a[j+i-1]-a[j])*(c[n]-c[j+i-1]+c[j]),
				f[j+1][j+i-1][0]+(a[j+1]-a[j])*(c[j]+c[n]-c[j+i-1]));
			f[j][j+i-1][1]=min(f[j][j+i-2][0]+(a[j+i-1]-a[j])*(c[n]-c[j+i-2]+c[j-1]),
				f[j][j+i-2][1]+(a[j+i-1]-a[j+i-2])*(c[n]-c[j+i-2]+c[j-1]));
		}
	}
	cout<<min(f[1][n][0],f[1][n][1]);
}

洛谷 3147

Bessie喜欢在手机上下游戏玩(……),然而她蹄子太大,很难在小小的手机屏幕上面操作。

她被她最近玩的一款游戏迷住了,游戏一开始有n个正整数,(2<=n<=262144),范围在1-40。在一步中,贝西可以选相邻的两个相同的数,然后合并成一个比原来的大一的数(例如两个7合并成一个8),目标是使得最大的数最大,请帮助Bessie来求最大值。
$$
f[i][j] 保存 i这个数 以 j作为开头的合并区间的结尾,若没有就是0
$$

#include<bits/stdc++.h>
using namespace std;
int n,i,x,j,s,f[60][300005];
int main()
{
	cin>>n;
	for (i=1;i<=n;i++)
	{
		cin>>x;
		f[x][i]=i+1;
	}
	for (i=2;i<=58;i++)
		for (j=1;j<=n;j++)
		{
			if (!f[i][j])
				f[i][j]=f[i-1][f[i-1][j]];
			if (f[i][j])
				s=i;
		}
	cout<<s<<'\n';
}

合唱队 洛谷3205

#include<bits/stdc++.h>
using namespace std;
int n,i,j,a[1005],f[1005][1005][2];
const int mod=19650827;
int main()
{
	cin>>n;
	for (i=1;i<=n;i++)
	{
		cin>>a[i];
		f[i][i][0]=1;
	}
	for (i=2;i<=n;i++)
		for (j=1;j<=n-i+1;j++)
		{
			if (a[j]<a[j+1])
				f[j][i+j-1][0]=(f[j][i+j-1][0]+f[j+1][i+j-1][0])%mod;
			if (a[j]<a[i+j-1])
				f[j][i+j-1][0]=(f[j][i+j-1][0]+f[j+1][i+j-1][1])%mod;
			if (a[i+j-1]>a[i+j-2])
				f[j][i+j-1][1]=(f[j][i+j-1][1]+f[j][i+j-2][1])%mod;
			if (a[i+j-1]>a[j])
				f[j][i+j-1][1]=(f[j][i+j-1][1]+f[j][i+j-2][0])%mod;
		}
	cout<<(f[1][n][0]+f[1][n][1])%mod<<'\n';
}

涂色 洛谷4170

假设你有一条长度为 $5$ 的木板,初始时没有涂过任何颜色。你希望把它的 $5$ 个单位长度分别涂上红、绿、蓝、绿、红色,用一个长度为 $5$ 的字符串表示这个目标:$\texttt{RGBGR}$。

每次你可以把一段连续的木板涂成一个给定的颜色,后涂的颜色覆盖先涂的颜色。例如第一次把木板涂成 $\texttt{RRRRR}$,第二次涂成 $\texttt{RGGGR}$,第三次涂成 $\texttt{RGBGR}$,达到目标。

用尽量少的涂色次数达到目标。

#include<bits/stdc++.h>
using namespace std;
int n,i,j,k,f[101][101];
string s;
int main()
{
	cin>>s;
	n=s.length();
	s='.'+s;
	memset(f,127,sizeof(f));
	for (i=1;i<=n;i++)
		f[i][i]=1;
	for (i=2;i<=n;i++)
		for (j=1;j<=n-i+1;j++)
		{
			if (s[j]==s[i+j-1])
				f[j][i+j-1]=min(f[j][i+j-2],f[j+1][i+j-1]);
			for (k=j;k<=i+j-2;k++)
				f[j][i+j-1]=min(f[j][i+j-1],f[j][k]+f[k+1][i+j-1]);
		}
	cout<<f[1][n];
}

玩具取名 洛谷4290

#include<bits/stdc++.h>
using namespace std;
int W,I,N,G,i,n,j,k,l,o;
string ww[20],ii[20],nn[20],gg[20],s;
bool f[205][205][4];
int judge(char ch)
{
	if (ch=='W') return 0;
	if (ch=='I') return 1;
	if (ch=='N') return 2;
	if (ch=='G') return 3;
	return -1;
}
int main()
{
	cin>>W>>I>>N>>G;
	for (i=1;i<=W;i++)
		cin>>ww[i];
	for (i=1;i<=I;i++)
		cin>>ii[i];
	for (i=1;i<=N;i++)
		cin>>nn[i];
	for (i=1;i<=G;i++)
		cin>>gg[i];
	cin>>s;
	n=s.length();
	s='.'+s;
	for (i=1;i<=n;i++)
		f[i][i][judge(s[i])]=1;
	for (i=2;i<=n;i++)
	{
		for (j=1,k=i;k<=n;j++,k++)
			for (l=j;l<=k-1;l++)
			{
				for (o=1;o<=W;o++)
					f[j][k][0]=f[j][k][0] or f[j][l][judge(ww[o][0])] and f[l+1][k][judge(ww[o][1])];
				for (o=1;o<=I;o++)
					f[j][k][1]=f[j][k][1] or f[j][l][judge(ii[o][0])] and f[l+1][k][judge(ii[o][1])];
				for (o=1;o<=N;o++)
					f[j][k][2]=f[j][k][2] or f[j][l][judge(nn[o][0])] and f[l+1][k][judge(nn[o][1])];
				for (o=1;o<=G;o++)
					f[j][k][3]=f[j][k][3] or f[j][l][judge(gg[o][0])] and f[l+1][k][judge(gg[o][1])];
			}
	}
	if (f[1][n][0])cout<<'W';
	if (f[1][n][1])cout<<'I';
	if (f[1][n][2])cout<<'N';
	if (f[1][n][3])cout<<'G';
	if ((!f[1][n][0])and(!f[1][n][1])and(!f[1][n][2])and(!f[1][n][3]))
		cout<<"The name is wrong!";
	cout<<'\n';
}

字符串折叠 洛谷4302

#include<bits/stdc++.h>
using namespace std;
string s;int n,i,l,k,o,r,len,t,w,f[105][105];
unsigned long long a[105],b[105];
const int base=23333233;
int main()
{
	cin>>s;
	n=s.length();
	s='.'+s;
	for (i=1;i<=n;i++)
		a[i]=a[i-1]*base+s[i];
	b[0]=1;
	for (i=1;i<=n;i++)
		b[i]=b[i-1]*base;
	memset(f,127,sizeof(f));
	for (i=1;i<=n;i++)
		f[i][i]=1;
	for (i=2;i<=n;i++)
	{
		for (l=1,r=i;r<=n;l++,r++)
		{
			len=r-l+1;
			for (k=1;k<=len/2;k++)
				if (len%k==0)
				{
					for (o=2;o<=len/k;o++)
						if (a[l+o*k-1]-a[(o-1)*k+l-1]*b[k]!=a[l+(o-1)*k-1]-a[(o-2)*k+l-1]*b[k])
							break;
					if (o!=len/k+1)
						continue;
					t=len/k;w=0;
					while (t>0)
					{
						t=t/10;
						w++;
					}
					f[l][r]=min(f[l][r],f[l][l+k-1]+2+w);
				}
			for (k=l;k<r;k++)
				f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);
		}
	}
	cout<<f[1][n]<<'\n';
}

Greedy Pie Eaters P 洛谷5851

#include<bits/stdc++.h>
using namespace std;
int n,m,i,j,l,r,k,a,b,c,f[305][305],g[305][305][305];
int main()
{
	cin>>n>>m;
	for (i=1;i<=m;i++)
	{
		cin>>a>>b>>c;
		for (j=b;j<=c;j++)
			g[j][b][c]=a;
	}
	for (i=1;i<=n;i++)
		for (j=i;j>=1;j--)
			for (k=i;k<=n;k++)
			{
				if (j!=1)g[i][j-1][k]=max(g[i][j-1][k],g[i][j][k]);
				if (k!=n)g[i][j][k+1]=max(g[i][j][k+1],g[i][j][k]);
			}
	for (i=1;i<=n;i++)
		for (l=1,r=i;r<=n;l++,r++)
		{
			for (k=l;k<r;k++)
				f[l][r]=max(f[l][r],f[l][k]+f[k+1][r]);
			for (k=l;k<=r;k++)
				f[l][r]=max(f[l][r],f[l][k-1]+f[k+1][r]+g[k][l][r]);
		}
	cout<<f[1][n]<<'\n';
}

合并饭团 洛谷4805

#include<bits/stdc++.h>
using namespace std;
int n,i,l,r,k,j,x,ma,t,w,m,f[505][505],a[505];
int main()
{
	cin>>n;
	for (i=1;i<=n;i++)
		for (j=i+1;j<=n;j++)
			f[i][j]=-1;
	for (i=1;i<=n;i++)
	{
		cin>>f[i][i];
		a[i]=a[i-1]+f[i][i];
	}
	for (i=2;i<=n;i++)
		for (l=1,r=i;r<=n;l++,r++)
			for (t=l,w=r-1;t<=w;t++)
			{
				while (a[r]-a[w]<a[t]-a[l-1])w--;
				if (w<t) break;
				if (a[r]-a[w]!=a[t]-a[l-1])
					continue;
				if ((f[l][t]!=-1)and(f[t+1][w]!=-1)and(f[w+1][r]!=-1)and(f[l][t]==f[w+1][r]))
					f[l][r]=max(f[l][r],f[l][t]+f[t+1][w]+f[w+1][r]);
			}
	for (i=1;i<=n;i++)
		for (j=i;j<=n;j++)
			ma=max(ma,f[i][j]);
	cout<<ma<<'\n';
}

标签:std,include,int,cin,区间,using,main,DP
From: https://www.cnblogs.com/ShadowAA/p/17320817.html

相关文章

  • 状压DP
    状压DP状压DP是动态规划的一种,通过将状态压缩为整数来达到优化转移的目的。例题售货员的难题洛谷1171#include<bits/stdc++.h>usingnamespacestd;intn,i,j,k,min1,a[25][25],f[1050000][25];intmain(){ cin>>n; for(i=1;i<=n;i++) for(j=1;j<=n;j++) cin>......
  • 树形DP
    树形DP树形DP,即在树上进行的DP。由于树固有的递归性质,树形DP一般都是递归进行的。例题没有上司的舞会洛谷1352#include<bits/stdc++.h>usingnamespacestd;intn,i,x,y,b[6005],f[6005][2];vector<int>a[6005];voidsc(intx){ for(inti=0;i<a[x].size();i++) ......
  • 数位DP
    数位DP数位是指把一个数字按照个、十、百、千等等一位一位地拆开,关注它每一位上的数字。如果拆的是十进制数,那么每一位数字都是0~9,其他进制可类比十进制。数位DP:用来解决一类特定问题,这种问题比较好辨认,一般具有这几个特征:要求统计满足一定条件的数的数量(即,最终目的为计数);......
  • DP优化
    DP优化单调队列优化WatchingFireworksisFunCF372C#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;lln,m,d,i,j,k,l,r,ma,f[2][150005],g[150005],a[305],b[305],c[305];intmain(){ cin>>n>>m>>d; for(i=1;i<=m;i++) ......
  • 线性DP
    线性DP最长公共子序列O(n*m)写法inta[MAXN],b[MAXM],f[MAXN][MAXM];intdp(){for(inti=1;i<=n;i++)for(intj=1;j<=m;j++)if(a[i]==b[j])f[i][j]=f[i-1][j-1]+1;elsef[i][j]=std::max(f[i-1][j],......
  • 背包DP
    背包DP二进制分组优化考虑优化。我们仍考虑把多重背包转化成0-1背包模型来求解。预处理物品数量是2的次方。且要覆盖物品数量的点。即2n次方+1到kindex=0;for(inti=1;i<=m;i++){intc=1,p,h,k;cin>>p>>h>>k;while(k>c){k-=c;......
  • PyQt5 软件在 macOS HiDPI 模式下出现字体模糊的问题
    ​ Retina屏幕是苹果公司在2010年在 WWDC上发布的一种高密度像素的屏幕。HiDPI是一种渲染技术,它可以让Retina屏幕上的图像更加清晰。HiDPI技术会将图像渲染成两倍于原始分辨率的大小,然后再将其缩小到原始分辨率的大小,这样就可以让图像更加清晰。PyQt5编写的软件在Wi......
  • 计算机网络 传输层协议TCP和UDP
    目录一、传输层协议二、tcp协议介绍三、tcp报文格式四、tcp三次握手五、tcp四次挥手六、udp协议介绍七、常见协议和端口八、有限状态机  一、传输层协议传输层协议主要是TCP和UDP协议主要作用1.分段和重组2.会话多路复用 二、tcp协议......
  • 神策数据入选 IDC 中国客户数据平台 CDP 市场规模及厂商份额报告
    近日,IDC首发中国客户数据平台CDP市场规模及厂商份额报告,明确了CDP产品的功能和使用方式,以便减少购买者的困惑。IDC市场份额报告调研的厂商包括神策数据在内的15家企业,报告显示,市场前5家公司营业额几乎占整个市场的二分之一(47.1%)。报告中,IDC将CDP产品的主要功能分为......
  • 解决 dpkg 安装出错后的 Sub-process /usr/bin/dpkg returned an error code (1) 错误
    在使用dpkg-i安装.deb软件包的过程中,会出现安装失败的可能。之后无论用sudoaptinstall-forsudaptautoremove等常见的修复命令都是无效的。网络上很多解决方案都直接给出需要运行的命令,不分析原因也不说明理由。我从来不尝试这样的解决方案,除非我自己知道或是只能死马......