# USACO4.4 三道题

26 篇文章 0 订阅

USACO4.4 三道题

这次三道题

Shuttle Puzzle 是普通题,可以找规律,可以搜索+剪枝.

Pollutant Control 是网络流,有几个难点需要仔细处理,不能直接套模板

Frame Up 是简单题…递归扫一遍,注意输出

shuttle

N = 3 
初始状态: WWW_BBB 
目标状态: BBB_WWW

N <= 12

求字典序最小的最小步数…

(找规律可以发现最小步数是N * (N+2))

深搜+剪枝..0s过(可以用规律优化)

  • (nocow)构造法

    官方图片

    根据答案寻找规律(可以证明正确性):

    3
    3 5 6 4 2 1 3 5 7 6 4 2 3 5 4
    2 1 -2 -2 -1 2 2 2 -1 -2 -2 1 2 -1
    
    4
    4 6 7 5 3 2 4 6 8 9 7 5 3 1 2 4 6 8 7 5 3 4 6 5
    2 1 -2 -2 -1 2 2 2 1 -2 -2 -2 -2 1 2 2 2 -1 -2 -2 1 2 -1
    
    5
    5 7 8 6 4 3 5 7 9 10 8 6 4 2 1 3 5 7 9 11 10 8 6 4 2 3 5 7 9 8 6 4 5 7 6
    2 1 -2 -2 -1 2 2 2 1 -2 -2 -2 -2 -1 2 2 2 2 2 -1 -2 -2 -2 -2 1 2 2 2 -1 -2 -2 1 2 -1
    
    6
    6 8 9 7 5 4 6 8 10 11 9 7 5 3 2 4 6 8 10 12 13 11 9 7 5 3 1 2 4 6 8 10 12 11 9 7 5 3 4 6 8 10 9 7 5 6 8 7
    2 1 -2 -2 -1 2 2 2 1 -2 -2 -2 -2 -1 2 2 2 2 2 1 -2 -2 -2 -2 -2 -2 1 2 2 2 2 2 -1 -2 -2 -2 -2 1 2 2 2 -1 -2 -2 1 2 -1
    
    
    先观察样例数据,如果把还没移动的那一步也算上,那么空格的位置为
    4 3 5 6 4 2 1 3 5 7 6 4 2 3 5 4 (n=3,样例)
    5 4 6 7 5 3 2 4 6 8 9 7 5 3 1 2 4 6 8 7 5 3 4 6 5 (n=4)
    我们凭借极其敏锐的眼光发现这组序列为
    435 642 1357 642 35 4 (n=3,样例)
    5 46 753 2468 97531 2468 753 46 5 (n=4)
    即长度为1,2,3,4,...,n,n+1,n,...,4,3,2,1这样的2n+1组等差序列
    我们讨论第1~n+1组序列,这些序列满足
      *公差的绝对值为2
      *奇数组为降序列,偶数组为升序列
      *对于第i组(1<=i<=n+1),若为奇数组则首项为n+i,偶数组则首项为n-i+2
    对于第n+2~2n+1组,可以由对称性求出。
    输出时从第二组开始即可。

    *mike6 不宜用最小割优化算法的最小割…

    V<=32,E<=1000的有向图,给出每个割的价值,求最小数目的最小价值割,有多组输出字典序最小的

    最大流=最小割中,最大流的意义就不大了…

    但是还是要套用最大流算法

  • 这道题尴尬的是输出,因此不能完全套用模板

    想了很久去看题解,输出字典序最小的话,那么最后就应该枚举边集

    (话说看题解释nocow吵的很开心..都说别人错了并给出范例数据= =)

    然后是最小数目的割,观察到E<=1000所以编码优化,存储流信息的时候,cost = c * 1001 + 1;

    然后用一个edge表存边,用邻接矩阵存图,由于V很小,没必要用邻接表优化,直接枚举就行

    (话说我也觉得一开始学这个算法就应该用枚举)

    输出最小价值就是cost/1001,最小割数就是cost%1001.(其实这个没有先后关系吧.)

  • 一堆WA给第一个网络流的bug警示

    • Dinic算法

      1. bfs时候起始点距离应该标记为1,不然可能有回边,这样会很麻烦
      2. dfs时候深搜下去是temp = dfs(p,min(ca,cap[fr][p]));然后当前位置矩阵和容量-temp,对称位置矩阵+temp.ca不能写成temp
      3. 输出字典序最小,那么应该设一个变量标记输出了多少个了,完成即退出
    • 算法简要描述

      1. bfs确定每一点到源点最近距离,源点为1.

      2. 如果终点距离存在,深搜扩展(源点,inf),否则退出算法

        • 深搜:

          1. 如果是终点返回扩展量

          2. 否则枚举可行边,进行扩展.基本模板如下

            long long temp,cnt = 0;
            for (int p = 1; p <= totNode; p++) {
                if (dis[p] == dis[fr] + 1 && cap[fr][p]) {
                    //cout << temp << " " << ca << endl;
                    temp = dfs(p,min(ca,cap[fr][p]));
                    ca   -= temp;
                    cap[fr][p] -= temp;
                    cap[p][fr] += temp;
                    cnt += temp;
                }
            }
    • min_cut算法

    void min_cut(){
        //广搜/floodfill包含源点联通区域(联通及f>0)
        int cnt = 0;
        for (int i = 1; i <= n; i+=2) 
            if (v[i]) //枚举联通区域每一点,确认割点
                for (int j = g[i]; j; j = e[j].nxt) 
                    if (!v[e[j].v] && e[j].f == 0) 
                        ans.push_back(e[j].v);
    
    }

Frame Up

给出一个形如下方的图层覆盖,求覆盖顺序

/*
矩形的边的宽度为 1 ,每条边的长度都不小于 3 。
矩形的每条边中,至少有一部分是可见的。注意,一个角同时属于两条边。
矩形用大写字母表示,并且每个矩形的表示符号都不相同。

30 30
..............................
.OOOOOOOOOYYYYYOO.............
.O....PPPPYPPPYPOPP...........
.O....P...Y...Y.O.P...........
.O....P...Y...Y.O.P...........
.O....P...Y...Y.O.P...........
.O....P...Y...Y.O.P...........
.O....P...Y...Y.O.P...........
.O....P...Y...Y.O.P...........
.O....P...Y...Y.O.P...........
.OOOOOOOOOYOOOYOEEEEEEEEE.....
......PPPPYPPPYPEPP.....E.....
..........Y...Y.E.......E.....
..WWWWWWWWWWWWWWWWWTT...E.....
..W...T...Y...Y.E.W.T...E.....
..W...T...Y...Y.E.W.T...E.....
..W...T...Y...Y.E.W.T...E.....
..W...T...YYYYY.EEWEEEEEE.....
UUWWWWWWWWWWWWWWWWW.T.........
U.....TTTTTTTTTTTTQQQQQQQQQQQ.
U....RRRRRRRRRRRRRQRRRRR....Q.
U....R............Q....R....Q.
UIIIIRRRRRRRRRRRRRQRRRRRIIIIQ.
UI................QQQQQQQQQQQ.
UUUUUUUUUUUUUUUUUUU........I..
.IIIIIIIIIIIIIIIIIIIIIIIIIII..
..............................
..............................
..............................
..............................

*/

本来想找标志的..看到规则这道题就很简单了

就是要注意输出顺序

读入的时候标记每个字符的最上最左最右最下….check是否为当前字符或者已经用了的字符

有一点栈的思想

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值