SRM 556 DIV2

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.这题很可惜,因为不熟悉vectorinsert而来不及在比赛的时候提交。虽然我后来交的时候也不能肯定算法一定是对的。

 

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;
        } 

 
}; 

 

 

 

原文地址:https://www.cnblogs.com/xchaos/p/2688160.html