HDU - 5203 Rikka with wood sticks 分析

题目大意:有n根连续的木棒,其中有m根是坏的,现在要求将这m根木棒切成连续的四段,使得其中三段中都不包含坏的木棒,且三段木棒的长度和最大,在最长的前提下看这三段木棒能否拼成三角形,如果能的话,问最多有多少种且木棒的方法

解题思路:要使三段都不含坏的木棒,就要把所有坏的木棒包含在一段里,就要找出坏的木棒的最小位置和最大位置,然后往这两处进行切割,这样就分成三段了,找出最长的那段再进行切割,再判断能否组成三角形即可(这是一般情况)

特殊情况下,坏的木棒是在第一根和最后一根,这要进行特殊处理
1。如果坏的木棒有第一根和最后一根,那么答案就是0了
2。如果第一根坏了且最后一根没坏,那么就找到最大的那根坏的木棒的位置进行切割,这样就剩下一段好的了
3。如果最后一根坏了且第一根没坏,那么就找到最小的那根坏的木棒的位置进行切割

考虑一下只剩一段如何求切割方法,这里借用了一下别人的图这里写图片描述

枚举x1,由组成三角形的条件可得
x1 + n - x1 - x2 > x2,即 n / 2 > x2
x1 + x2 > n - x1 - x2,即x2 > n / 2 - x1
x2 + n - x1 - x2 > x1,即n / 2 > x1

有上面可得 n / 2 -x1 < x2 < n / 2
因为是小于而不是小于等于(例子是n=4,x1 = 1的时候),所以上面的式子要改为n / 2 - x1 < x2 < (n-1) / 2
所以只要枚举所有的x2就是所有的切割方法了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1010

int main() {
    int n ,m;
    while(scanf("%d%d", &n, &m) == 2) { 
        int Min = n + 1, Max = -1, pos;
        for(int i = 0; i < m; i++) {
            scanf("%d", &pos);
            Min = min(Min,pos);
            Max = max(Max,pos);
        }

        if(Min == 1 && Max == n) {
            printf("0\n");
            continue;
        }

        int len1, len2;
        len1 = Min - 1;
        len2 = n - Max;

        if(len1 > len2)
            swap(len1,len2);

        int L , R;
        if(Min == 1 || Max == n) {
            long long ans = 0;
            for(int i = 1; i < n; i++) {
                if(i >= len2 - i) 
                    break;  

                L = (len2 - 2 * i) / 2;
                R = (len2 - 1) / 2;
                ans += (R - L);
            }
            printf("%I64d\n",ans);
            continue;
        }
        else {
            long long ans = 0;
            int t;
            for(int i = 1; i < len2; i++) {
                t = len2 - i;
                if(len1 + 2 * i > len2 && len1 + len2 > 2 * i)
                    ans++;
            }
            printf("%I64d\n",ans);  
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值