1733D1&D2解题报告

1733D1

题目大意:给出两个长度为n的01串,每次能选择两个位置进行取反,相邻的位置取反代价为x,不相邻则为y,问让其中一串变成另一串的最小代价

初遇想法

对于两个串上01不同的位置可以直接发现

相邻代价为$min$($x$,$y/times2$)

不相邻代价为$min$($x/times$两点距离,$y$)

并且若01不同的位置是奇数显然无解

由于直接忽略了题给的$x$和$y$的大小条件,以至于我陷入了D2的思考。

考虑贪心,每两个点直接进行代价的判断

显然最后为了纠正这个错误的想法花了相当大的力气

further

根据题给条件,发现出题人希望让我们去多使用不相邻的两点

反思和提醒之后发现,把视线只放在两点是很局限的一种判断

只要超过三个点,我们可以直接跨点构造出不相邻

结论

特判长度是否为2,即无法构造不不相邻

否则全部构造成不相邻

代码如下

#include <bits/stdc++.h>
using namespace std;
int a[100000],b[100000];
vector<int> s;
int read()
{
	int ret(0);
	char ch=getchar();
	while (ch!='0'&&ch!='1') ch=getchar();
	return ch-48;
}
int main()
{
	int t;
	scanf("%d",&t);
	while (t--)
	{
		s.clear();
		long long n,x,y;
		scanf("%lld%lld%lld",&n,&x,&y);
		for (int i=1;i<=n;i++) a[i]=read();
		for (int i=1;i<=n;i++) b[i]=read();
		for (int i=1;i<=n;i++)
			if (a[i]!=b[i]) s.push_back(i);
		int len=s.size()-1;long long ans(0);
		if ((len+1)%2==0)
		{
			if (len+1>2) printf("%lld\n",y*(len+1)/2);
			else 
			{
				if (len+1==0) printf("0\n");
				else if (s[0]+1==s[1]) printf("%lld\n",min(y*2,x));
				else printf("%lld\n",y);
			}
		}
		else printf("-1\n");
	}
	return 0;
}

1733D2

$n^3dp$很显然

$n^3$的问题在于枚举断点,联系上一题,长度大于4,就可以强行构造不相邻,所以断点是长度为4的时候

$n^2$dp即可

#include <bits/stdc++.h>
using namespace std;
int a[100000],b[100000];
vector<int> s;
long long x,y;
long long dp[5010][5010]; 
long long solve(int a,int b)
{
	if (a+1==b) return min(x,y*2);
	else return min(x*(b-a),y);   
}
int read()
{
	int ret(0);
	char ch=getchar();
	while (ch!='0'&&ch!='1') ch=getchar();
	return ch-48;
}
int main()
{
	int t;
	scanf("%d",&t);
	while (t--)
	{
		s.clear();
		long long n;
		scanf("%lld%lld%lld",&n,&x,&y);
		for (int i=1;i<=n;i++) a[i]=read();
		for (int i=1;i<=n;i++) b[i]=read();
		s.push_back(0);
		for (int i=1;i<=n;i++)
			if (a[i]!=b[i]) s.push_back(i);
		int len=s.size()-1;
		for (int i=1;i<=len;i++)
		for (int j=1;j<=len;j++) 
		dp[i][j]=0x3f3f3f3f3f3f3f3f;
		//printf("len=%d\n",len);
		if (len==0) printf("0\n");
		else
		{
			if (len&1) printf("-1\n");
			else
			{
				for (int i=1;i<len;i++) 
					dp[i][i+1]=solve(s[i],s[i+1]);
			//	for (int i=1;i<len;i++)
			//		printf("%d %d %lld\n",i,i+1,dp[i][i+1]);
				for	(int i=3;i<len;i+=2)
				{
						for (int l=1;l<=len-i;l++)
						{
							int r=l+i;
							//printf("%d %d %dQQQ\n",l,r,i);
							dp[l][r]=min(dp[l][r-2]+solve(s[r-1],s[r]),dp[l+2][r]+solve(s[l],s[l+1]));
							dp[l][r]=min(dp[l][r],dp[l+1][r-1]+solve(s[l],s[r]));
							dp[l][r]=min(dp[l][r],y*(r-l+1)/2);  
							if (len>=5) dp[l][r]=min(dp[l][l+3]+dp[l+4][r],dp[l][r]);
							
						}
				}
				printf("%lld\n",dp[1][len]);
			}
		}
	}
	return 0;
}
posted @ 2022-09-21 19:58  by_wang  阅读(31)  评论(0)    收藏  举报
Live2D