cf 85 E. Petya and Spiders

http://codeforces.com/contest/112/problem/E

轮廓线dp。每个格子中的蜘蛛选一个去向,最终,使每个蜘蛛都有一个去向,同时保证有蜘蛛的格子最少。需要用4进制模拟

此题还可以用DLX+二分来解,这个解法相对于轮廓线dp就很无脑了,不用考虑细节。以后再补上

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <vector>
#include <set>
using namespace std;

typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 100010;
int n, m;
const int MALL = 1 << 14;

int dp[2][MALL];
///00 up, left; 01 stall; 10 right; 11 down;
int now, next;
int ALL;
int ans;
void update(int r, int nextr, int val)
{
    nextr &= ALL;
    dp[next][nextr] = max(dp[next][nextr], dp[now][r] + val);
}
int getI(int x, int i)
{
    return (x >> (2 * i))&3;
}
int main()
{
    while (cin >> n >> m)
    {
        if (n < m) swap(n, m);
        ALL = (1 << (m * 2)) - 1;

        memset(dp, -1, sizeof(dp));
        dp[0][0] = 0;
        now = 0; next = 1;

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                for (int r = 0; r <= ALL; r++)
                {
                    if (dp[now][r] != -1)
                    if ((j && getI(r, 0) == 2) || (i && getI(r, m - 1) == 3))
                    {
                        update(r, (r << 2) + 1, 0);
                        continue;
                    }
                    update(r, (r << 2) + 1, 0);
                    if (j && getI(r, 0) == 1 ) update(r, r << 2, 1);///left 00

                    if (i && getI(r, m - 1) == 1 ) update(r, r << 2, 1);///up 00

                    if (j < m - 1) update(r, (r << 2) + 2, 1);///right 10

                    if (i < n - 1) update(r, (r << 2) + 3, 1);///down 11
                }
                memset(dp[now], -1, sizeof(dp[now]));
                next = now; now ^= 1;
            }
        }
        ans = 0;
        for (int i = 0; i <= ALL; i++)
            ans = max(ans, dp[now][i]);
        cout << ans << endl;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
解法:贪心算法 如果两个字符串不相等,那么它们必定至少有一位不一样。考虑对于这一位,我们应该对字符串 a 进行哪种操作,才能使得它更接近于字符串 b。 首先,我们可以通过交换字符串 a 中的两个数字,使得这一位变为我们想要的数字。如果我们把这一位变成了 b 中的数字,那么显然这一位就不需要再进行修改了。因此,我们只需要考虑把这一位变成 a 中的数字 4 或 7。 如果我们把这一位变成 a 中的数字,则需要执行一次操作;如果我们把这一位变成 a 中的数字,则需要执行一次操作。那么,我们应该采取哪种操作呢? 我们可以贪心地想,如果我们把这一位变成 a 中的数字,那么这一位和 b 中的数字就越相似,那么接下来的操作就越容易执行。因此,我们应该选择将这一位变成 a 中的数字,从而尽可能地增加和 b 相同的数字的数量。 实现时,我们可以从左到右扫描字符串 a 和 b,统计它们不同的位置的数量。对于每个不同的位置,我们都可以选择将这一位变成 4 或 7,然后更新 a 中数字 4 和 7 的数量。最终,我们就可以得到将字符串 a 转换为字符串 b 所需的最少操作数。 时间复杂度 字符串 a 和 b 的长度为 n,我们需要扫描一遍字符串并统计数字 4 和 7 的数量,因此时间复杂度为 O(n)。 空间复杂度 我们只需要存储数字 4 和 7 的数量,因此空间复杂度为 O(1)。 Python 代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值