564 Find the Closest Palindrome:给出一个长度不超过18的非负整数,求出与其最近接的回文整数(不包括它自己)。
思路:假设其长度为偶数。将其分为两半,前一半设为$x$,那么最后的答案的前一部分一定是$x-1,x,x+1$三个中的一个。在这里,$x-1$有可能变成少一位的数字,比如100到99; $x+1$可能多一位,比如99到100.长度为奇数时类似的思路。
long long strToInt(string s) {
long long t=0;
for(int i=0;i<(int)s.size();++i) {
t=t*10+s[i]-'0';
}
return t;
}
string intToString(long long x) {
if(x==0) return "0";
stack<int> st;
while(x) {
st.push(x%10);
x/=10;
}
string s="";
while(!st.empty()) {
s+='0'+st.top();
st.pop();
}
return s;
}
void up(long long &x,long long p,long long q) {
if(p==q) return;
if(x==-1) {
x=p;
}
else if(abs(p-q)<abs(x-q)) {
x=p;
}
}
string revStr(string s) {
int ll=0,rr=(int)s.size()-1;
while(ll<rr) {
swap(s[ll++],s[rr--]);
}
return s;
}
class Solution {
public:
string nearestPalindromic(string s) {
long long x=strToInt(s);
int n=(int)s.size();
if(s.size()==1) {
if(s=="0") return "1";
return intToString(x-1);
}
long long ans=-1;
if(n&1) {
long long t0=strToInt(s.substr(0,n/2+1));
for(int i=-1;i<=1;++i) {
string s1=intToString(t0+i);
string s2=s1;
revStr(s1.substr(0,s1.size()-(s1.size()==n/2+1)));
if(s1.size()<n/2+1) {
s2+=s1;
}
else if(s1.size()==n/2+1) {
s2+=revStr(s1.substr(0,n/2));
}
else {
s2+=revStr(s1.substr(0,s1.size()-2));
}
long long k=strToInt(s2);
up(ans,k,x);
}
}
else {
long long t0=strToInt(s.substr(0,n>>1));
if(t0==1) {
up(ans,9,x);
up(ans,11,x);
up(ans,22,x);
return intToString(ans);
}
for(int i=-1;i<=1;++i) {
string s1=intToString(t0+i);
string s2=s1;
if(s1.size()<n/2) {
s2+=revStr(s1+"9");
}
else if(s1.size()==n/2) {
s2+=revStr(s1);
}
else {
s2+=revStr(s1.substr(0,n/2));
}
long long k=strToInt(s2);
up(ans,k,x);
}
}
return intToString(ans);
}
};
546 Remove Boxes:给定一个长度不超过100的整数数列。每次可以删除连续的相同的一段(删除后两端的会连接到一起)。设该次删除的数字的个数为$k$,那么将得到$k*k$个分数。选择一种删除的序列,使得删除完所有数字后得到的分数最多?
思路:对于某一段连续的数字,可以将其单独删除,或者是跟其他的连在一起的时候再删除。设$f[L][R][k]$表示现在删除$[L,R]$之间的所有数字,且$R$位置之后有$k$个数字跟$R$位置上的数字相同.如果单独删除$R$以及后面的数字,有分数$f[L][R-1][0]+(1+k)^{2}$;否则可以选择跟之前的某一段合并,设合并的位置为$t$,那么有$f[L][t][k+1]+f[t+1][R-1][0]$。
实际实现的时候可以将连续相同的进行合并,速度会快一些。
vector<pair<int,int>> all;
int f[111][111][111];
int dfs(int L,int R,int k) {
if(L>R) return 0;
if(f[L][R][k]!=-1) return f[L][R][k];
if(L==R) return (k+all[L].second)*(k+all[L].second);
int &ans=f[L][R][k];
ans=dfs(L,R-1,0)+(k+all[R].second)*(k+all[R].second);
for(int i=R-1;i>=L;--i) {
if(all[i].first==all[R].first) {
int tmp=dfs(L,i,all[R].second+k)+dfs(i+1,R-1,0);
ans=max(ans,tmp);
}
}
return ans;
}
class Solution {
public:
int removeBoxes(vector<int>& a) {
all.clear();
int n=(int)a.size();
if(n==0) return 0;
all.push_back(make_pair(a[0],1));
for(int i=1;i<n;++i) {
if(a[i]==all.back().first) {
++all.back().second;
}
else {
all.push_back(make_pair(a[i],1));
}
}
memset(f,-1,sizeof(f));
return dfs(0,(int)all.size()-1,0);
}
};