[NOIP2010]引水入城

传送门
思路:拿到这道题我就开始想不到正解就开始应该怎么搜(汗),不过还是好,能拿到70分(因为我舍弃了一种情况,就是从一个蓄水站往下走到另外一个沿湖城市,这种搜了很花时间)。听到正解发现我的思路真是不够,真是不行,我们可以发现每一个沿海城市能够到达的城市是连续的,所以我们就可以用一个N³搜索将原问题转化为一个区间覆盖问题,然后就可以水过了。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 250005
#define MAXM 1000005
int dd[4][2] = {0,1,0,-1,1,0,-1,0};
int mp[505][505], sx[505][505], sy[505][505], I, ld[505], rd[505], n, m;
int col[505];
bool vis[505][505];
bool dfs(int x, int y)
{
    if(vis[x][y] && x != 1) return sx[x][y];
    vis[x][y] = 1;
    if(x == 1) return 1;
    for(int i = 0; i < 4; i ++)
    {
        int tx = x + dd[i][0], ty = y + dd[i][1];
        if(tx < 1 || tx > n || ty > m || ty < 1) continue;
        if(mp[tx][ty] > mp[x][y]) if(dfs(tx, ty)) {sx[x][y] = tx, sy[x][y] = ty; break;}
    }
    return sx[x][y];
}
int ans = 0x3f3f3f3f;
struct E
{
    int l, r;
    bool operator < (const E rhs) const
    {
        return l < rhs.l;
    }
}e[505];
int L, R, cnt, dp[505];
void dfs1(int x, int y)
{
    if(x == n)
    {
        if(L > y) L = y;
        if(R < y) R = y;
    }
    for(int i = 0; i < 4; i ++)
    {
        int tx = x + dd[i][0], ty = y + dd[i][1];
        if(tx < 1 || tx > n || ty > m || ty < 1) continue;
        if(mp[tx][ty] < mp[x][y]) dfs1(tx, ty);
    }
    return;
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
            scanf("%d", &mp[i][j]);
    if(n == 1)
    {
        int answer = 0;
        for(int i = 1; i <= m; i ++)
            if(mp[1][i] >= mp[1][i-1] && mp[1][i] >= mp[1][i+1]) answer ++;
        printf("1\n%d\n", answer);
        return 0;
    }
    int flag = 0;
    for(int i = 1; i <= m; i ++)
        if(dfs(n, i)) flag ++;
    if(flag != m)
    {
        printf("0\n%d\n", m - flag);
        return 0;
    }
    for(int i = 1; i <= m; i ++)
    {
        L = 505, R = -1;
        dfs1(1, i);
        if(R != -1) {e[++ cnt].l = L;e[cnt].r = R;}
    }
    memset(dp, 0x3f, sizeof dp);
    dp[0] = 0;
    for(int i = 1; i <= m; i ++)
        for(int j = 1; j <= cnt; j ++)
            if(i >= e[j].l && i <= e[j].r && dp[i] > dp[e[j].l-1] + 1)
                dp[i] = dp[e[j].l-1] + 1;
    printf("1\n%d\n", dp[m]);
    return 0;
}

转载于:https://www.cnblogs.com/geng4512/p/5296925.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2010年全国青少年信息学奥林匹克联赛(NOIP)提高组的复赛是一次重要的比赛。在这次比赛中,参赛选手需要展示出在信息学方面的专业知识和技能。 比赛的复赛共有两个题目,分别是算法设计题和程序设计题。算法设计题要求选手设计一个高效的算法来解决特定的问题,参赛选手需要对问题进行深入分析,找到最佳的解决方案。程序设计题要求选手根据题目要求,使用编程语言编写出能够正确解决问题的程序。 在比赛中,选手们需要在限定的时间内完成这两个题目。时间限制会对选手的应试能力和抗压能力提出要求。选手需要利用自己所学的知识和经验,灵活地运用在实际的问题中,制定出最佳的解决方案。 在复赛中,评委们会根据选手的算法设计和程序设计的质量来进行评判。他们会考察选手的算法思路是否清晰,是否能通过代码来实现自己的想法。评委们还会参考选手的编码风格,包括代码的可读性和规范性。这些综合因素将影响选手在比赛中的表现。 参加2010年NOIP提高组的复赛对于选手们来说是一次难得的机会。这次比赛既能测试选手们的能力和水平,也能提供一个展示自己的舞台。在这个比赛中,选手们需要充分发挥自己的优势,努力争取好的成绩,并从中积累经验,提高自己的编程能力和解决问题的能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值