250pt
题意:
给定一个字符串,求没有重复字符的最长子串。
分析:
直接暴力枚举所有子串(开始位置和结束位置)。
View Code
class ChocolateBar { public: int maxLength(string s) { int i,j,k,t,ii,flag,a[28],n=s.size(); for(i=k=0;i<n;i++) for(j=i;j<n;j++) { memset(a,0,sizeof(a)); t=0; flag=1; for(ii=i;ii<=j;ii++) a[s[ii]-'a']++; for(ii=0;ii<28;ii++) if(a[ii]) { t++; if(a[ii]>1) flag=0; } if(flag&&t>k) k=t; } return k; } };
500pt:
题意:
旅行商问题的变种。
给定顶点不超过50个的图和它们之间的边,每个顶点都有一个权值(0<=v<1024),一个旅行商一开始在第0个点,权值为v[0],只要右边,可以任意访问任何顶点,每到一个,已获得的权值更新异或该点权值,求在此过程中,权值的最大值。
分析:
广搜。因为权值的范围很小,所以可用顶点和权值表示状态。用dp[i,j]的值表示能否在第i个顶点达到权值j。
PS.没注意到权值的范围很小,以为要深搜加剪枝,遇到搜索就发憷,一看别人代码就知道怎么写了。读题还是不够仔细。
View Code
class XorTravelingSalesman { public: bool dp[51][1024]; int maxProfit(vector <int> v, vector <string> r) { int i,j,k,ret,n=v.size(); ret=v[0]; memset(dp,false,sizeof(dp)); queue<pair<int ,int> > q; q.push(make_pair(0,v[0])); dp[0][v[0]]=true; while(!q.empty()) { i=q.front().first; k=q.front().second; q.pop(); for(j=0;j<n;j++) if(r[i][j]=='Y'&&!dp[j][k^v[j]]) { dp[j][k^v[j]]=true; if((k^v[j])>ret) ret=(k^v[j]); q.push(make_pair(j,k^v[j])); } } return ret; } };
1000pt:
题意:
给定一个数列,从左到右依次取数,取出组成一个新数列,取出的数可以放到新数列的左边或右边,求使开头第一个数不为0,字典序最小的新数列。
分析:
一开始想贪心,取出的数只要和新数列的最左边数比较,小或等则放左,大则放右。
因为前导0的干扰,此法不可行。后来转到动态规划,发现状态不好表示。又转回贪心,只要事先去掉前导0的干扰就完全可行,即先找到新数列的最左边的数(从旧数列右往左找最小数),最小数之后的数全放有侧,之前的数按照前法贪心。
PS.这题很可惜,因为不熟悉vector的insert而来不及在比赛的时候提交。虽然我后来交的时候也不能肯定算法一定是对的。
View Code
class LeftRightDigitsGame { public: string minNumber(string s) { int i,j,k,l,a[55],n=s.size(); string ret; memset(a,0,sizeof(a)); for(j=n-1;s[j]=='0';j--); for(i=n-1;i>=0;i--) if(s[i]!='0'&&s[i]<s[j]) j=i; for(k=n-1;k>j;k--) a[k]=1; a[k]=0; l=s[0]-'0'; for(i=1;i<k;i++) if(s[i]-'0'<=l) l=s[i]-'0',a[i]=0; else a[i]=1; ret.push_back(s[0]); for(i=1;i<n;i++) if(a[i]) ret.push_back(s[i]); else ret.insert(ret.begin(),s[i]); return ret; } };