10.11考试总结

10.11考试总结

全是DP实际上发现暴力也能有部分分.......

三角形牧场

DP......当时总是感觉不像啊

需要处理的就是枚举三角形边长可能出现的情况。因为周长在输入端时候就可以确定了,所以只需要通过枚举两条边就可以强行算出第三条边.....

所以就省空间+时间....

f[0][0] = 1;
    for (int i=1; i<=n; ++i)
        for(int j=half; j>=0; j--)
            for(int k=j; k>=0; k--)
                if(j >= d[i] && f[j-d[i]][k] || k >= d[i] && f[j][k-d[i]])
                    f[j][k] = 1;

查找边数的存在情况

然后就是判断是否能组成三角形与否

for (int i=half; i>=1; --i)
    for (int j=i; j>=1; --j)
        if (f[i][j])
            f (check(i, j, tot - i - j))
                ans = max(ans, area(i, j, tot - i - j));

然后就做完了.......

多米诺骨牌

又是DP.......我莫得感情直接算出上下的差,然后直接计算一边。不过这个有负数的答案出现,所以要处理一下变成正数就好了...

然后再找答案就好了

for(int i=1; i<=n; i++)
    for(int j=-5000; j<=5000; j++)
        f[i][j+M] = min(f[i-1][j-c[i]+M], f[i-1][j+c[i]+M]+1);
for(int i=0; i<=5000; i++)
{
    ans = min(f[n][i+M], f[n][-i+M]);
    if(ans <= 1000)//因为n小于1000,所以最多翻转肯定是1000以内
    {
        printf("%d\n", ans);
        break;
    }
}

修剪草坪

把自己列出的公式推导一下。

首先f[i]是作为一个结束点,f[j]是断点。

所以

f[i]=max(f[i],f[j-1]+a[j+1]+a[j+2]……a[i])(i-k<=j<=i)

然后发现可以上一波前缀和优化。

f[i]=max(f[i],f[j-1]+sum[i]-sum[j]) (i-k<=j<=i)

然后发现在i中,sum[i]其实是一个定值,所以可以提出来

f[i]=max(f[i],f[j-1]-sum[j])+sum[i] (i-k<=j<=i)

发现只与j有关联,并且始终找最大值。

然后滚去了解了一下什么是单调队列,保证队列内数字单调,输出前面的最大值就可以了

IL ll top(int i)
{
    d[i] = f[i-1] - sum[i];
    while (head <= tail && d[q[tail]] < d[i]) tail--;
    q[++tail] = i;
    while (head <= tail && q[head] < i - k) head++;
    return d[q[head]];
}

单调队列,然后用这个来找最大值

for(int i=1; i<=n; i++) f[i] = top(i) + sum[i];

一个简单的任务

这个任务并不简单

状压DP......劝退

猜你喜欢

转载自www.cnblogs.com/rendex/p/9782562.html