hdu 6080 度度熊保护村庄

本文介绍了一个关于防守最优策略的问题,通过定义一个特定的方向并寻找最小包围圈来解决问题。利用C++实现算法,通过有向线段确定点的位置,并找到能够恰好包围所有住房的最小环。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

哗啦啦村袭击了喵哈哈村!
度度熊为了拯救喵哈哈村,带着自己的伙伴去救援喵哈哈村去了!度度熊与伙伴们很快的就过来占据了喵哈哈村的各个军事要地,牢牢的守住了喵哈哈村。
但是度度熊发现,这是一场旷日持久的战斗,所以度度熊决定要以逸待劳,保存尽量多的体力,去迎战哗啦啦村的战士。
于是度度熊决定派尽量多的人去休息,但是同时也不能松懈对喵哈哈村的保护。
换句话而言,度度熊希望尽量多的人休息,而且存在一个包围圈由剩下的人组成,且能够恰好的包围住喵哈哈村的所有住房(包括边界)。
请问最多能让多少个人休息呢?

题解

当时看这个题的时候,完全不会做-w-
于是今天重新看了一次
发现我会做啦!!这好像没什么好骄傲啊吧
我们认为地规定一个方向,就是让点都在有向线段的左边
然后找最小环就可以了
CODE:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX=1<<28;
const int N=505;
int n,m;
int f[N][N];
struct qq
{
    int x,y;
}a[N],b[N];
int mul (qq x,qq y,qq z)
{
    int x1=x.x-z.x,y1=x.y-z.y;
    int x2=y.x-z.x,y2=y.y-z.y;
    return x1*y2-x2*y1;
}
int main()
{
    while (scanf("%d",&n)!=EOF)
    {
        for (int u=1;u<=n;u++)  scanf("%d%d",&a[u].x,&a[u].y);
        scanf("%d",&m);
        for (int u=1;u<=m;u++)  scanf("%d%d",&b[u].x,&b[u].y);
        for (int u=1;u<=m;u++)
            for (int i=1;i<=m;i++)
            {
                if (u==i) 
                {
                    f[u][i]=MAX;
                    continue;
                }
                int cnt=0,cnt1=0;
                for (int j=1;j<=n;j++)
                {
                    if (mul(a[j],b[u],b[i])>0) cnt++;
                    if (mul(a[j],b[u],b[i])<0) cnt1++;
                    if (cnt!=0) break;
                }
                if (cnt==0) f[u][i]=1;
                else f[u][i]=MAX;
            }
        /*for (int u=1;u<=m;u++)
        {
            for (int i=1;i<=m;i++)
                printf("%d ",f[u][i]);
            printf("\n");
        }*/
        for (int u=1;u<=m;u++)
            for (int i=1;i<=m;i++)
            {
                if (f[i][u]==MAX) continue;
                for (int j=1;j<=m;j++)
                    f[i][j]=min(f[i][j],f[i][u]+f[u][j]);
            }
        /*for (int u=1;u<=m;u++)
        {
            for (int i=1;i<=m;i++)
                printf("%d ",f[u][i]);
            printf("\n");
        }*/
        int ans=MAX;
        for (int u=1;u<=m;u++)
            ans=min(ans,f[u][u]);
        if (ans==MAX) printf("ToT\n");
        else printf("%d\n",m-ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值