HDU 6103 Kirinriki 尺取法

写一个反思吧,这道题拿到手真的是没有什么思路,尺取法也不是很熟悉。
题目链接

  • 为什么想到用尺取法:题目要求的是一个有限定条件连续区间最大长度,即可联想到尺取法

尺取法要求所选取的区间有一定的变化趋势的情况,通俗地说,在对所选取区间进行判断之后,我们可以明确如何进一步有方向地推进区间端点以求解满足条件的区间,如果已经判断了目前所选取的区间,但却无法确定所要求解的区间如何进一步得到根据其端点得到,那么尺取法便是不可行的。
参考:尺取法 — 详解 + 例题模板(全)

  • 为什么能用尺取法:
    在这里能用尺取法是由于dis是随着长度递增的[1],我们就是根据它来判断每一步该如何推进的。(即端点该如何变化)

  • 如何想到利用对称来使用尺取法:
    这道题想要利用尺取法,就得选定一个易于使用尺取法的状态。由于尺取法能减少遍历次数就是因为它能存储当前状态的数据,所以必然要固定起点。
    而现在有两个串,并且两个串长度相同,所以可以想到利用对称来使用尺取法。

AC代码:

#include
#include
#include
using namespace std;
const int MAX_N=5005;
char s[MAX_N];
inline int fabs(int a)
{
	return a>0?a:-a;
}
int main()
{
	ios::sync_with_stdio(false);
	int t;
	cin>>t;
	while(t--)
	{
		int m;
		cin>>m;
		cin>>s;
		int len = strlen(s);
		int maxlen=0;
		for(int dui=0;dui<2*len-3;dui++)	//dui表示对称轴编号 
		{
			int l,r,sum=0,r1,l1;
			l=dui/2+1,r=dui/2+1;
			r1=dui/2,l1=dui/2;
			if(dui%2)l++,r++;
			while(r<len&&r1>=0)
			{
				while(sum<=m&&r1>=0&&r<len)
				{
					sum+=fabs(s[r1]-s[r]);
					r++,r1--;
				}
				if(sum<=m)
				{
					maxlen=max(maxlen,r-l);
					break;
				}
				maxlen=max(maxlen,r-l-1);
				sum-=fabs(s[l]-s[l1]);
				l++,l1--;
			}
		}
		cout<<maxlen<<endl;
	}
	return 0;
}

你可能感兴趣的:(尺取法,算法)