USACO--2.1The Castle

思路:这个题目难在建图,开始的时候我想把每个房间没有墙的面求出来,然后再和他邻近的房间加上一条边进行建图,后面发现要通过题目给定的条件求出房间那个面没有墙是十分困难的;后面参考了别人的思路,我们记录每个房间那几面是有墙的(这个很容易做到),然后就不显示建图了,直接通过dfs标记的思想求出这个图所有的连通块(Flood fill 算法)。后面的处理就比较简单了,求出这个连通块后就可以知道总共有几个房间了,最大的房间有多大;然后我们再依次试探拆除每个房间的N,E面的墙壁,看一下能得到的最大房间的数量。
对于题目中:
Choose the optimal wall to remove from the set of optimal walls by choosing the module farthest to the west (and then, if still tied, farthest to the south). If still tied, choose ‘N’ before ‘E’. Name that wall by naming the module that borders it on either the west or south, along with a direction of N or E giving the location of the wall with respect to the module.
这段话,开始的时候我很是不能理解,后面才知道,他的意思是:在大的方向上我们要优先拆除西面和然后是南面,对于每个小的房间我们应该优先拆除北面然后是东面。果然是英语太渣。。。。。。

代码如下:

/*
ID: 15674811
LANG: C++
TASK: castle
*/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<fstream>
using namespace std;

///南东北西
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};

///西南北东
///int dx1[]={0,1,-1,0};
///int dy1[]={-1,0,0,1};
///北东
int dx1[]={-1,0};
int dy1[]={0,1};

int vis[55][55],n,m;
char name[]={'N','E'};

typedef struct
{
    bool flag[5];
}P;
P p[55][55];

void dfs(int x,int y,int flag)
{
     for(int k=0;k<4;k++)
     {
         if(p[x][y].flag[k])
             continue;
         int xx=x+dx[k];
         int yy=y+dy[k];
         if(xx<1||xx>n||yy<1||yy>m)
            continue;
         if(vis[xx][yy])
            continue;
         vis[xx][yy]=flag;
         dfs(xx,yy,flag);
     }
}

int main()
{
    ofstream fout("castle.out");
    ifstream fin("castle.in");
    //ifstream fin("lkl.txt");
    while(fin>>m>>n)
    {
        memset(p,0,sizeof(p));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                int x;
                fin>>x;
                if(x>=8) p[i][j].flag[0]=true,x-=8;
                if(x>=4) p[i][j].flag[1]=true,x-=4;
                if(x>=2) p[i][j].flag[2]=true,x-=2;
                if(x>=1) p[i][j].flag[3]=true;
            }
         int cnt=0;
         for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(vis[i][j])
                    continue;
                vis[i][j]=++cnt;
                dfs(i,j,cnt);
            }
         int num[3000];
         memset(num,0,sizeof(num));
         int Max=0;
         for(int i=1;i<=n;i++)
           for(int j=1;j<=m;j++)
           {
               num[vis[i][j]]++;
               Max=max(Max,num[vis[i][j]]);
           }
         fout<<cnt<<endl<<Max<<endl;
         int room=0,rx,ry,k;
         for(int x=1;x<=n;x++)
            for(int y=1;y<=m;y++)
            {
                for(int d=0;d<2;d++)
                {
                    int xx=x+dx1[d];
                    int yy=y+dy1[d];
                    if(xx<1||xx>n||yy<1||yy>m)
                        continue;
                    if(vis[x][y]==vis[xx][yy])
                        continue;
                    int tmp=num[vis[x][y]]+num[vis[xx][yy]];
                    if(room<tmp)
                    {
                        rx=x; ry=y;
                        room=tmp;
                        k=d;
                    }
                    else if(room==tmp)
                    {
                       if(y<=ry)
                       {
                           if(rx==x&&ry==y) ///同一个格子北东都可以要保证北优先
                              continue;
                           rx=x; ry=y;
                           k=d;
                       }
                    }
                }
            }
        fout<<room<<endl;
        fout<<rx<<" "<<ry<<" "<<name[k]<<endl;
    }
  return 0;
}
### USACO 1327 Problem Explanation USACO 1327涉及的是一个贪心算法中的区间覆盖问题。具体来说,这个问题描述了一组奶牛可以工作的班次范围,并要求找出最少数量的奶牛来完全覆盖所有的班次。 对于此类问题的一个有效方法是采用贪心策略[^1]。首先按照区间的结束时间从小到大排序这些工作时间段;如果结束时间相同,则按开始时间从早到晚排列。接着遍历这个有序列表,在每一步都尽可能选择最早能完成当前未被覆盖部分的工作时段。通过这种方式逐步构建最终解集直到所有的时间段都被覆盖为止。 为了提高效率并防止超时错误,建议使用`scanf()`函数代替标准输入流操作符`cin`来进行数据读取处理[^2]。 ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; struct Interval { int start; int end; }; bool compareIntervals(const Interval& i1, const Interval& i2) { return (i1.end < i2.end || (i1.end == i2.end && i1.start < i2.start)); } int main() { vector<Interval> intervals = {{1, 7}, {3, 6}, {6, 10}}; sort(intervals.begin(), intervals.end(), compareIntervals); int currentEnd = 0; int count = 0; for (const auto& interval : intervals) { if (interval.start > currentEnd) break; while (!intervals.empty() && intervals.front().start <= currentEnd) { if (intervals.front().end >= interval.end) { interval = intervals.front(); } intervals.erase(intervals.begin()); } currentEnd = interval.end; ++count; if (currentEnd >= 10) break; // Assuming total shift length is known. } cout << "Minimum number of cows needed: " << count << endl; } ``` 此代码片段展示了如何实现上述提到的方法解决该类问题。需要注意的是实际比赛中可能还需要考虑更多边界条件以及优化细节以满足严格的性能需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值