周练回顾(3)

洛谷 P3143 Diamond Collector S
Bessie想把大小相差不超过K的钻石同时放在一个陈列架上,它有两个陈列架,问最多能放多少钻石。
贪心,排序就完了,但是重点是怎么找出其中两个长度最长的区间。莽了一个多小时失败了,看有人用双指针的做法。我一下想起来不久前做的一个前后缀的题和这个很像(P6877 長いだけのネクタイ),不知道做了多久终于a了…
先排序,然后从数组的前、后开始递推,找出从开始往后每一点的最大区间长度和尾部往前每一点的最大区间长度,记录在两个数组中。这样就能找出两个最大区间了。但是要防备区间重合的情况,用ansr[i]+ansl[i+1]就可以了。

#include 
using namespace std;
long long int a[50002];
const long long int mod=1e9+7;
long long int ansl[50002],ansr[50002];
int main()
{
    long long int k,n,i,ans=1,m=1,l,r,u;
    cin>>n>>k;
    for(i=0;i<n;i++)
    {
        cin>>a[i];
        ansr[i]=1;
        ansl[i]=1;
    }
    sort(a,a+n);
    r=1;
    for(i=0;i<n;i++)
    {
        while(a[r]-a[i]<=k)
        {   if(r==n) break;
         ansr[r]=max(ansr[r-1],r-i+1);
            r++;
        }
    }
    l=n-2;
    for(i=n-1;i>=0;i--)
    {
        while(a[i]-a[l]<=k)
        {   if(l<0) break;
         ansl[l]=max(ansl[l+1],i-l+1);
            l--;
        }
    }
    for(i=0;i<n;i++)
    {
        ans=max(ans,ansr[i]+ansl[i+1]);
    }
    cout<<ans<<endl;
    return 0;
}

洛谷 p1680 奇怪的分组
写在前一篇了…
洛谷 P1057 传球游戏
给定人数n和传球次数m,每次可以向左和右传球,求最后传回本人手中的方案数。
开始我用的递归,只有60分。果然30的数据量都不行,想了一会没有剪枝的思路,就换用dp做了(后来知道可以暴力打表,用递归算出答案直接if打出来,学到了学到了)
二维dp,i代表传球次数,j代表当前所在位置,裸题,唯一要注意的就是它是个圆,在两边的时候要构建新的dp方程。

#include 
using namespace std;
int n, m, f[31][31];
int main()
{
    cin >> n >> m;
    f[0][1] = 1;
    for(int i = 1; i <= m; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if(j+1>n)
            {
                f[i][j]=f[i-1][1]+f[i-1][j-1];
                continue;
            }
            if(j-1==0)
            {
                f[i][j]=f[i-1][j+1]+f[i-1][n];
                continue;
            }
            f[i][j] = f[i-1][j+1] + f[i-1][j-1];
        }
    }
    cout <<f[m][1];
    return 0;
}

洛谷 P1025 数的划分
将整数n分成k份,求有多少种分法。
虽然洛谷的数据很强,但还是被我找到漏洞了(比起dfs还是暴力更香)
n只有200,而且k最大只有6,顺序不同也是相同的分法,所以为了避免重复就从小的开始分,并且后面分的数一定不能比前面的小(不然肯定就重复了)这样就可以判断出每个位置有多少种可能…直接暴力列举k,最多也就五重循环。

#include 
using namespace std;
int main()
{
    long long int ans=0;
    int i,j,k,l,p,w,n,t;
    cin>>n>>k;
    if(k==2){
        cout<<n/2<<endl;return 0;
    }
    if(k==3){
        t=n/3;
        for(i=1;i<=t;i++)
        {
            for(j=i;j<=(n-i)/2;j++)
            {
                ans++;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    if(k==4){
    for(i=1;i<=n/4;i++)
    {
        for(j=i;j<=(n-i)/3;j++)
        {
            for(l=j;l<=(n-i-j)/2;l++)
            {
                ans++;
            }
        }
    }
    cout<<ans<<endl; return 0;
    }
    if(k==5){
           for(i=1;i<=n/5;i++)
    {
        for(j=i;j<=(n-i)/4;j++)
        {
            for(l=j;l<=(n-i-j)/3;l++)
            {
                for(p=l;p<=(n-i-j-l)/2;p++)
                {
                    ans++;
                }
            }
        }
    }
    cout<<ans<<endl; return 0;
    }
    if(k==6){
        for(i=1;i<=n/6;i++)
    {
        for(j=i;j<=(n-i)/5;j++)
        {
            for(l=j;l<=(n-i-j)/4;l++)
            {
                for(p=l;p<=(n-i-j-l)/3;p++)
                {
                    for(w=p;w<=(n-i-j-l-p)/2;w++)
                    {
                        ans++;
                    }
                }
            }
        }
    }
     cout<<ans<<endl; return 0;
    }
}

这周度过了数学竞赛和英语四级笔试的模拟考,好不容易想点份饺子,这都能送错楼,倒霉死了…

你可能感兴趣的:(贪心算法,算法,动态规划)