SRM 547 DIV2

250pt

数学模型:

  求顶角是120度的等腰三角形的面积

分析:

  L*L*sqrt(3.0)/4.0,

  计算的时候为了提高精度,先乘后除。

 

View Code
class MinimalTriangle 
{ 
        public: 
        double maximalArea(int length) 
        { 
                double l=length,t=sqrt(3.0);
    return l*l*t/4.0;
        } 
        
}; 

 

500pt

数学模型:

给定n组点,每组横坐标相同,第一组:(0,1)(0,2)......(0,h[0]);.......第组:((n-1)*w,1),((n-1)*w,2)......((n-1)*w,h[n-1]),相邻两组的的横坐标相差w。在每组中任选一个点,连接相邻两组所选的点,求这条折线的总长。

分析:比赛时猜想贪心,但证明不了,赛后证明是错的,还是用DP稳妥点

  1,枚举每组的每个点

    dp[i][j]表示选定第i组纵坐标为j的点时最长折线长度

    dp[i][j]=(dp[i-1][k],hypot(k-j,w))(1<=k<=h[i-1]);复杂度O(N^3)

  2,赛后看有人是贪心加动态规划做的,每次只用考虑每组的最高点和最低点。

    和它们之间的状态转移,复杂度是O(n)

结:SRM比赛中,在时间限制内,编写出尽量正确且容易编写的代码,正确和短码的优先级比效率要高

  此方法可扩展到二维?

 

枚举+动态规划

O(n^3)
class PillarsDivTwo 
{ 
        public: 
        double maximalLength(vector <int> h, int w) 
        { 
            int i,j,k,n=h.size();
            double dp[60][110]={0};
            if(n==1)
                return 0.0;
            for(i=1;i<n;i++)
                for(j=1;j<=h[i];j++)
                    for(k=1;k<=h[i-1];k++)
                        dp[i][j]=max(dp[i][j],dp[i-1][k]+hypot(abs(j-k)*1.0,w*1.0));
            for(j=k=1;j<=h[n-1];j++)
                if(dp[n-1][j]>dp[n-1][k])
                    k=j;
            return dp[n-1][k];
        } 
        
 
}; 

贪心+动态规划

O(N)
class PillarsDivTwo 
{ 
        public: 
        double maximalLength(vector <int> h, int w) 
        { 
            int i,j,k,n=h.size();
            double dp[111][2]={0};
            for(i=1;i<n;i++)
            {
                dp[i][0]=max(dp[i-1][0]+w,dp[i-1][1]+hypot(h[i-1]-1,w));
                dp[i][1]=max(dp[i-1][0]+hypot(h[i]-1,w),dp[i-1][1]+hypot(1.0*abs(h[i-1]-h[i]),w));
            }
            return max(dp[n-1][0],dp[n-1][1]);
        } 
        
 
}; 

1000pt

数学模型:

  给定一个数值范围是1100的整数集合,求一个子集,使元素互质且个数最多。

 

分析:比赛的时候没想太多,直接深度优先搜索枚举每个子集,再加优化。但是犯了一个致命错误:1左移的结果是long long,应该是强制转为long long ,(long long)1;赛后改了但是超时,看别人代码居然是状态压缩动态规划,我当时想过但觉得会超时。

  重新读题,发现没有充分利用范围是1100这个条件,再考虑互质的本质:即有除1以外的公约数,任何整数都可以由质数的连乘组成,那么互质就是有公约数,而且公约是是质数,即可以用质数的集合来表示这些整数,24,可用{2,3},整数的互质就可用交集为空来表示,而这些集合最多有25个元素(100以内有25个质数),但是状态数太多,会超时;再看50以上的质数与所有其它的数都互质,所以可以预处理,那么只剩下15个,集合可用一个整数(0~(1<<15)-1)表示,每个二进制位表示一个元素,1没有该元素,0表示已有该元素。

 

结:读题要仔细,充利用题目条件,条件不同,算法完全不同

超时的深搜
class RelativelyPrimeSubset 
{ 
        public:
        long long n,b[55];
        int ans;
        int gcd(int a,int b)
        {
            return b?gcd(b,a%b):a;
        }
        void DFS(long long k,int cnt,long long t)
        {
            if(k==n)
            {
                ans=max(ans,cnt);
                return ;
            }
            if(cnt+n-k<=ans)
                return ;
            if(t&((long long)1<<k))
                DFS(k+1,cnt+1,t&b[k]);
            DFS(k+1,cnt,t);
        }
        int findSize(vector <int> a) 
        { 
                long long i,j;
                n=(long long)a.size();
                ans=1;
                for(i=0;i<n;i++)
                    for(j=0,b[i]=0;j<n;j++)
                        if(gcd(a[i],a[j])==1)
                            b[i]|=((long long)1<<j);
                for(i=0;i<n;i++)
                    DFS(i+1,1,b[i]);
                return ans;
        } 
        
 
}; 

 O(N*(1<<15))

状态压缩DP
class RelativelyPrimeSubset 
{ 
       public:
    int f[1<<15];
        int findSize(vector <int> S) 
        {
            int i,j,k,n,m,ret,empty,c[51],a[111]={0},p[111],d[51];
            bool b[51]={false};
            for(i=2;i<100;i++)
                if(!a[i])
                {
                    for(j=i+i;j<=100;j+=i)
                        a[j]=1;
                }
            m=0;
            sort(S.begin(),S.end());
            if(S[0]==1)
                m++,S.erase(S.begin());
            n=S.size();
            for(i=0;i<n;i++)
                if(!a[S[i]])
                {
                    m++;
                    for(j=i;j<n;j++)
                        if(S[j]%S[i]==0)
                            b[j]=true;
                }
            for(i=j=0;i<n;i++)
                if(!b[i])
                {
                    c[j++]=S[i];
                    printf("%d ",S[i]);
                    for(k=2;k<100;k++)
                        if(!a[k]&&S[i]%k==0)
                            a[k]=-1;
                }
            n=j;
            if(!n)
                return m;
            for(i=2,k=0;i<100;i++)
                if(a[i]==-1)
                    p[k++]=i;
            for(i=0;i<n;i++)
                for(d[i]=j=0;j<k;j++)
                    if(c[i]%p[j]==0)
                        d[i]|=(1<<j);
            memset(f,0,sizeof(f));
            empty=(1<<k);
            for(i=empty-1;i>=0;i--)
                for(j=0;j<n;j++)
                    if((i&d[j])==0)
                        f[i]=max(f[i^d[j]]+1,f[i]);
            ret=0;
            for(i=0;i<empty;i++)
                ret=max(f[i],ret);
            return ret+m;
        } 
        
 
};  
原文地址:https://www.cnblogs.com/xchaos/p/2574564.html