百毒之星資格賽A題

很巧妙的建圖題

度度熊保護村莊
Problem Description
嘩啦啦村襲擊了喵哈哈村!度度熊爲了拯救喵哈哈村,帶着自己的夥伴去救援喵哈哈村去了!度度熊與夥伴們很快的就過來佔據了喵哈哈村的各個軍事要地,牢牢的守住了喵哈哈村。但是度度熊發現,這是一場曠日持久的戰鬥,所以度度熊決定要以逸待勞,保存儘量多的體力,去迎戰嘩啦啦村的戰士。於是度度熊決定派儘量多的人去休息,但是同時也不能鬆懈對喵哈哈村的保護。換句話而言,度度熊希望儘量多的人休息,而且存在一個包圍圈由剩下的人組成,且能夠恰好的包圍住喵哈哈村的所有住房(包括邊界)。請問最多能讓多少個人休息呢?

Input
本題包含若干組測試數據。
第一行一個整數n,表示喵哈哈村的住房數量。
接下來n行,每行兩個整數(x1[i],y1[i]),表示喵哈哈村的住房座標。
第n+1行一個整數m,表示度度熊的士兵數量。
接下來m行,每行兩個整數(x2[i],y2[i]),表示度度熊夥伴的座標。
滿足:
1<=n,m<=500
-10000<=x1[i],x2[i],y1[i],y2[i]<=10000
Output
請輸出最多的人員休息的數目。
如果無法保護整個村莊的話,輸出”ToT”
Sample Input
2
1 1
2 2
4
0 0
0 4
4 2
4 0
1
1 1
2
0 0
0 1

Sample Output
1
ToT


  • 對於每個有序點對(i,j),若所有房子都在點對的右側,則在圖上記dist(i,j)爲1,否則爲無窮。
  • 在處理完所有有序點(i,j)之後就可以得到一個有向圖,找到圖上的最小環就是m-答案。
#include <bits/stdc++.h>
#define clr(x,y) memset(x,y,sizeof x)
#define inf 0x3f3f3f3f
using namespace std;
struct Point { int x,y; }point[550],h[550];
struct Vec { int x,y; Vec(int _x,int _y):x(_x),y(_y){} };
int Cross(Vec a,Vec b)  { return a.x*b.y - b.x*a.y; }
int n,m,mp[550][550];
bool jgmid(Point a,Point b,Point c) { if (c.x>=min(a.x,b.x)&&c.x<=max(a.x,b.x)&&c.y>= min(a.y,b.y)&&c.y<=max(a.y,b.y)) return true; else return false; }
int main()
{
    int n;
    while (scanf("%d",&n)!=EOF)
    {
        for (int i=1;i<=n;i++) scanf("%d%d",&h[i].x,&h[i].y);
        scanf("%d",&m);
        for (int i=1;i<=m;i++) scanf("%d%d",&point[i].x,&point[i].y);
        clr(mp,inf);
        for (int i=1;i<=m;i++)
            for (int j=1;j<=m;j++)
            {
                bool flag=true;
                int tmp;
                 Vec l(point[i].x-point[j].x,point[i].y-point[j].y);
                for (int k=1;k<=n;k++)
                if ((tmp=Cross(l,Vec(point[i].x-h[k].x,point[i].y-h[k].y))) <0 || (tmp==0 && !jgmid(point[i],point[j],h[k])))
                { flag=false;if(!flag)break;}
                if (flag) mp[i][j]=1;
            }
        for (int k=1;k<=m;k++) for (int i=1;i<=m;i++) if (mp[i][k]!=inf) for (int j=1;j<=m;j++) mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
        int res=inf; for (int i=1;i<=m;i++) res=min(res,mp[i][i]);
        if (res>=inf)  printf("ToT\n"); else printf("%d\n",m-res);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章