洛谷 3528 libreoj 2170 [POI2011]PAT-Sticks

博客介绍了如何解决POI2011竞赛中的PAT-Sticks问题,即给定多个颜色和长度的木棍,找出能构成三角形的三个不同颜色的木棍。通过按长度排序并使用SPJ进行多解判断,采用枚举和替换策略优化解决方案,确保在不超过特定限制的情况下找到合法组合。

博客观赏效果更佳

题意简述

给你一些木棍,每个木棍有长度和颜色。输出一种方案,选择三个木棍,使得颜色不一样且能拼成一个三角形。开 S P J SPJ SPJ,多解输出任意一个。

木棍数量 n < = 1000000 n<=1000000 n<=1000000,颜色数量 k < = 50 k<=50 k<=50

思路框架

按长度排序,每次更新答案。

具体思路

首先木棍显然是无序的。无序的问题,就先无脑排序一下(如果复杂度能承受)。没问题的。

然后我们用一个长度为 3 3 3的数组表示答案。每次枚举 i i i,表示我们必须要把 i i i放到答案中(如果合法)

如果我们的答案中已经有一个和 i i i同颜色的木棍,那么我们肯定是换掉来的好,因为 i i i的长度肯定大于这根木棍的长度。(我们排过序,记得么)

然后如果没有相同的颜色,就用它换掉最短的那个木棍。这样显然也是更好的。

然后检测一下是否合法。如果合法,就输出答案,然后直接退出程序即可。

代码

#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
    #define N 1666666
    #define F(i,l,r) for(int i=l;i<=r;++i)
    #define D(i,r,l) for(int i=r;i>=l;--i)
    #define Fs(i,l,r,c) for(int i=l;i<=r;c)
    #define Ds(i,r,l,c) for(int i=r;i>=l;c)
    #define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
    #define MEM(x,a) memset(x,a,sizeof(x))
    #define FK(x) MEM(x,0)

    struct node
    {
        int col,len;
    }a[N];int cnt=0;
    bool operator<(node a,node b){return a.len<b.len;}
    int k;
    void R1(int &x)
    {
        x=0;char c=getchar();int f=1;
        while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        x=(f==1)?x:-x;
    }
    void Input()
    {
        R1(k);
        cnt=0;
        F(i,1,k)
        {
            int n;R1(n);
            F(j,1,n)
            {
                int len;R1(len);
                a[++cnt]=(node){i,len};
            }
        }
    }

    node ans[4];
    void Soviet()
    {
        sort(a+1,a+cnt+1);
        FK(ans);

        F(i,1,cnt)
        {
            bool flag=false;
            F(j,1,3)
            {
                if (a[i].col==ans[j].col)//相同颜色
                {
                    ans[j].len=a[i].len;
                    flag=true;
                }
            }

            if (!flag)//没有相同的颜色
            {
                ans[1]=a[i];//换掉最小的
            }
            sort(ans+1,ans+4);
            if (ans[1].len+ans[2].len>ans[3].len)//检测
            {
                F(j,1,3) printf("%d %d ",ans[j].col,ans[j].len);
                putchar('\n');
                return;
            }
        }
        puts("NIE");
    }

    #define Flan void
    Flan IsMyWife()
    {
        Input();
        Soviet();
    }
}
int main()
{
    Flandre_Scarlet::IsMyWife();
    getchar();getchar();
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值