zoj 3816 Generalized Palindromic Number

5 篇文章 0 订阅

A number that will be the same when it is written forwards or backwards is known as a palindromic number. For example, 1234321 is a palindromic number.

We call a number generalized palindromic number, if after merging all the consecutive same digits, the resulting number is a palindromic number. For example, 122111 is a generalized palindromic number. Because after merging, 122111 turns into 121 which is a palindromic number.

Now you are given a positive integer N, please find the largest generalized palindromic number less than N.

Input

There are multiple test cases. The first line of input contains an integer T (about 5000) indicating the number of test cases. For each test case:

There is only one integer N (1 <= N <= 1018).

Output

For each test case, output the largest generalized palindromic number less than N.

Sample Input
4
12
123
1224
1122
Sample Output
11
121
1221
1121
Solution:
看到此题,首先想到是贪心或者深搜的做法,但对于贪心,感觉比较烦琐PS:可能用贪心也做不了,弱菜一个。
深搜方法:
因为压缩后要成为一个回文串,所以可以利用这一点来剪枝
为了利用这一点,在深搜时保持状态
char* compress //搜索到当前位置为止,压缩后的数组
int compresslen //压缩后的的数组长度
int ind //下一个要搜的位置
 
我们也看到压缩后的回文串肯定是一个奇数长度的串,也就有一个中间的点,如此,我便在状态中加入了这个点
int peak//回文串中间点
还保存了一个搜索到目前为止,对于前面的字符是否有所改变
bool changed //前面对应的字符串是否已经改变
 
结束搜索:
是否有已经加入回文串中间点,并且余下没有搜索的字符串 等于压缩字符串成为一个回文串所需要的最少字符
或者没有回文串中间点,可以直接剪枝等等的先剪了。
进一步:
枚举当前字符的范围,并讨论是否可压缩,是否设置中间点,当然这两类情况需要比较哪种情况更好。
 
由于深搜索没有考虑10000   100001等情况,所以后面特殊讨论。
 
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 50;
char s[N];
char globalchange[N];
char stype1[N];
char stypy2[N];

int len;

bool dfs(char* compress,int compresslen,int ind,bool changed,int peak)
{
	if(len == 1) {globalchange[0] = s[0] - 1;return true;}
	if((peak + 4) && (2*peak == compresslen -1 +len -ind))
	{
		if(changed)
		{
			for(int t = ind; t<len; t++)
				globalchange[t] = compress[len-t-1];
			return true;
		}
		int flag = 0;
		for(int t = ind; t<len; t++)
		{
			if(s[t] < compress[len-t-1] && !flag) return false;
			if(s[t] > compress[len-t-1]) flag = 1;
			globalchange[t] = compress[len-t-1];
		}
		if(flag) return true;
		else return false;
	}
	else if((peak+4) && (2*peak > compresslen - 1  + len - ind)) return false;
	else if(!(peak+4) && compresslen > len-ind-1) return false;

	for(char loopi = changed?'9':s[ind]; loopi >= '0'; loopi--)
	{
		globalchange[ind] = loopi;

		bool res = false;
		//peak;
		if((peak+4))
		{
			if(compress[compresslen-1] == loopi) res = dfs(compress,compresslen,ind+1,changed || (loopi != s[ind]),peak);
			else 
			{   
				if(compress[peak-(compresslen-peak-1)-1] == loopi)
				{
					compress[compresslen] = loopi;
					res = dfs(compress,compresslen+1,ind+1,changed || (loopi != s[ind]),peak);
				}
			}
			if(res) return true;
		}
		else
		{  
			memset(stype1,0,sizeof(stype1));
			memset(stypy2,0,sizeof(stypy2));

			if(compresslen != 0 && compress[compresslen-1] == loopi) res =dfs(compress,compresslen,ind+1,changed || (loopi != s[ind]),peak);
			else
			{
				compress[compresslen] = loopi;
				res = dfs(compress,compresslen+1,ind+1,changed || (loopi != s[ind]),peak);
			}
			if(res) {strcpy(stype1,globalchange);}

			if(compresslen!=0 && compress[compresslen-1] == loopi) res = dfs(compress,compresslen,ind+1,changed || (loopi != s[ind]),compresslen-1);
			else 
			{
				compress[compresslen] = loopi;
				res = dfs(compress,compresslen+1,ind+1,changed || (loopi != s[ind]),compresslen);
			}
			if(res) {strcpy(stypy2,globalchange);}

			if(stype1[0] != '\0' || stypy2[0] != '\0'){
				int r = strcmp(stype1,stypy2);
				if(r > 0) strcpy(globalchange,stype1);
				else strcpy(globalchange,stypy2);
				return true;
			}
		}
	}
	return false;
}
bool change()
{
	if((s[0] == '1') && (s[len-1] >='0' && s[len-1] <= '1'))
	{
	   int i =1;
	   int flag = 0;
	   while(i<len-1)
	   {
		   if(s[i] != '0') return false;
		   i++;
	   }
	   for(int j=0;j<len-1;j++)
		  printf("9");
	   printf("\n");
	   return true;
	}
	return false;
}
int main()
{
	int test;
	scanf("%d",&test);
	while(test -- )
	{
		scanf("%s",s);
		len = strlen(s);
		if((len == 1) && s[0] == '1') {printf("0\n");continue;}
		if(change()) continue;

		memset(globalchange,0,sizeof(globalchange));
		char temp[N];
		memset(temp,0,sizeof(temp));
		bool res = dfs(temp,0,0,false,-4);
		printf("%s\n",globalchange);
	}
	return 0;
}



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值