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......劝退
原文地址:https://www.cnblogs.com/rendex/p/9782562.html
时间: 2024-10-08 07:10:50