思维 2016.8.13

转自:《算法竞赛入门经典:训练指南》(好书

1、UVa 11300 Spreading the Wealth(分金币)

题意:

圆桌旁坐着 n 个人,每人有一定数量的金币,金币总数能被 n 整除

每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等

你的任务是求出被转手的金币数量的最小值

比如,n=4,且 4 个人的金币数量分别为 1,2,5,4 时,只需转移 4 枚金币(第3 个人给第 2 个人两枚金币,第 2 个人和第 4 个人分别给第 1 个人 1 枚金币)

即可实现每人手中的金币数目相等

【输入格式】
输入包含多组数据。每组数据第一行为整数 n(n≤1 000 000),以下 n 行每行为一个整数,按逆时针顺序给出每个人拥有的金币数。输入结束标志为文件结束符(EOF)

【输出格式】
对于每组数据,输出被转手金币数量的最小值。输入保证这个值在 64 位无符号整数范围内

【样例输入】
3
100
100
100
4
1
2
5
4
【样例输出】
0
4
【分析】

这道题目看起来很复杂,让我们慢慢分析

首先,最终每个人的金币数量可以计算出来,它等于金币总数除以人数 n,接下来我们用 M 来表示每人最终拥有的金币数

假设有 4 个人,按顺序编号为 1,2,3,4

假设 1 号给 2 号 3 枚金币,然后 2 号又给 1 号 5 枚金币,这实际上等价于 2 号给 1 号 2 枚金币,而 1 号什么也没给 2 号

这样,可以设 x2 表示 2 号给了 1 号多少个金币。如果 x2 < 0 说明实际上是 1 号给了 2 号 x2 枚金币

x1,x3 和 x4 的含义类似,注意,由于是环形,x1 指的是 1 号给 4 号多少金币


现在假设编号为 i 的人初始有 Ai 枚金币,对于 1 号来说,他给了 4 号 x1 枚金币,还剩 A1 - x1 枚;但因为 2 号给了他 x2 枚金币,所以最后还剩 A1 - x1 + x2 枚金币

根据题设,该金币数量等于 M。换句话说,我们得到了一个方程:A1 - x1 + x2 = M


同理,对于第 2 个人,有 A2 - x2 + x3 = M。最终,我们可以得到 n 个方程,一共有 n 个变量,是不是可以直接解方程组了呢?

很可惜,还不行。因为从前 n-1 个方程推导出最后一个方程。所以,实际上只有 n-1 个方程式有用的


尽管无法直接解出答案,我们还是可以尝试着用 x1 表示出其他的 xi,则本题就变成了单变量的极值问题

对于第 1 个人,A1 - x1 + x2 = M -> x2 = M - A1 + x1 = x1 - C1 (规定 C1 = A1 - M,下面类似)

对于第 2 个人,A2 - x2 + x3 = M -> x3 = M - A2 + x2 = 2M - A1 - A2 + x1 = x1 - C2

对于第 3 个人,A3 - x3 + x4 = M -> x4 = M - A3 + x3 = 3M - A1 - A2 - A3 + x1 = x1 - C3

...

对于第 n 个人,An - xn + x1 = M。这是一个多余的等式,并不能给我们更多的信息


我们希望所有 xi 的绝对值之和尽量小,即 |x1| + |x1 - C1| + |x1 - C2| + ... + |x1 - Cn-1 要最小

注意到 |x - Ci| 的几何意义是数轴上点 x1 到 Ci 的距离,所以问题变成了:给定数轴上的 n 个点,找出一个到它们的距离之和尽量小的点


下一步可能有些跳跃。不难猜到,这个最优的 x1 就是这些数的“中位数”(即排序以后位于中间的数),因此只需要排个序就可以了

性急的读者可能又想跳过证明了,但是希望您这次能好好读一读,因为它实在是太优美,太巧妙了,而且不少其它题目也能用上


注意,我们要证明的是:给定数轴上的 n 个点,在数轴上的所有点中,中位数离所有顶点的距离之和最小

凡是能转化为这个模型的题目都可以用中位数求解,并不只适用于本题


让我们把数轴和上面的点画出来,如图所示


任意找一个点,比如图中的灰点。它左边有 4 个输入点,右边有 2 个输入点。把它往左移动一点,不要移地太多,以免碰到输入点

假设移动了 d 单位距离,则灰点左边 4 个点到它的距离各减少 d,右边的两个点到它的距离各增加了 d,但总的来说,距离之和减少了 2d

如果灰点的左边有 2 个点,右边有 4 个点,道理类似,不过应该向右移动。换句话说,只要灰点左右的输入点不一样多,就不是最优解

什么情况下左右的输入点一样多呢?

如果输入点一共有奇数个,则灰点必须和中间的那个点重合(中位数);如果有偶数个,则灰点可以位于最中间的两个点之间的任意位置(还是中位数)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e6 + 10;
ll num[maxn];
ll n;
vector<ll> V;

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    while (scanf("%lld", &n) != EOF) {
        V.clear();
        ll sum = 0;
        for (int i = 0; i < n; ++i) {
            scanf("%lld", &num[i]);
            sum += num[i];
        }
        ll average = sum / n;
        sum = 0;
        for (ll i = 0; i < n; ++i) {
            sum += num[i];
            ll t = sum - (i+1) * average;
            V.push_back(t);
        }
        sort(V.begin(), V.end());
        ll key = V[n/2];
        ull ans = 0;
        for (int i = 0; i < n; ++i) {
            ans += abs(V[i] - key);
        }
        printf("%llu\n", ans);
    }
    return 0;
}


2、UVALive 3708 Graveyard (墓地雕塑)

题意:

在一个周长为 10000 的圆上等距分布着 n 个雕塑。现在又有 m 个新雕塑加入(位置可以随意放),希望所有 n+m 个雕塑在圆周上均匀分布

这就需要移动其中一些原有的雕塑。要求 n 个雕塑移动的总距离尽量小

【输入格式】
输入包含若干组数据。每组数据仅一行,包含两个整数 n 和 m(2≤n≤1 000,1≤m ≤1 000),即原始的雕塑数量和新加的雕塑数量。输入结束标志为文件结束符(EOF)

【输出格式】
输入仅一行,为最小总距离,精确到 10^(-4)
【样例输入】
2 1
2 3
3 1
10 10

【样例输出】
1666.6667
1000.0
1666.6667
0.0
【样例解释】
前 3 个样例如图所示。白色空心点表示等距点,黑色线段表示已有雕塑


【分析】

请仔细看样例

3 个样例具有一个共同的特点:有一个雕塑没有移动

如果该特点在所有情况下都成立,则所有雕塑的最终位置(称为“目标点”)实际上已经确定

为了简单起见,我们把没动的那个雕塑作为坐标原点,其他雕塑按照逆时针顺序标上到原点的距离标号,如图所示


注意,这里的距离并不是真实距离,而是按比例缩小以后的距离

接下来,我们把每个雕像移动到离它最近的位置

如果没有两个雕像移到相同的位置,那么这样的移动一定是最优的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>

using namespace std;

#define PI acos(-1.0)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
int n, m;

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    while (scanf("%d%d", &n, &m) != EOF) {
        double ans = 0.0;
        for (int i = 1; i < n; ++i) {
            double t = double(i) / n * (n+m);
            ans += fabs(t - floor(t + 0.5)) / (n+m);
        }
        printf("%.4f\n", ans*10000);
    }
    return 0;
}

注意在代码中,坐标为 t 的雕塑移动到的目标位置是 floor(t + 0.5),也就是 t 四舍五入后的结果。这就是坐标缩小的好处


这个代码很神奇地通过了测试,但我们不知道会不会有两个雕塑会移动到相同的位置

这个“漏洞”有两种修补方法

第一种方法相对比较容易实施:由于题目中规定了 n,m ≤ 1000,我们只需要在程序里加入一个功能 -- 记录每座雕像移到的目标位置,就可以用程序判断是否会出现“人多坑少”的情况

这里可以明确地告诉大家:这样的情况不会出现

这样,即使无法从理论上证明,也可以确保在题目规定的范围内,我们的算法是严密的

第二种方法是直接证明。在我们的程序中,当坐标系缩放之后,坐标为 x 的雕塑被移动到了 x 四舍五入后的位置。

如果有两个坐标分别为 x 和 y 的雕塑被移动到了同一位置,说明 x 和 y 四舍五入后的结果相同,换句话说,即 x 和 y “很接近”

至于有多接近呢?差距最大的情况不外乎类似于 x = 0.5,y = 1.499999...。即便是这样的情况,y - x 仍然小于 1(尽管很接近 1),但这是不可能的,因为新增雕塑之后,相邻雕塑的距离才等于 1,之前的雕塑数目更少,距离应当更大才对


3、UVa 10881 Piotr's Ants(蚂蚁)

一根长度为 L 厘米的木棍上有 n 只蚂蚁,每只蚂蚁要么朝左爬,要么朝右爬,速度为 1厘米/秒

当两只蚂蚁相撞时,二者同时掉头(掉头时间忽略不计)。给出每只蚂蚁的初始位置和朝向,计算 T 秒之后每只蚂蚁的位置

【输入格式】
输入的第一行为数据组数。每组数据的第一行为 3 个正整数 L, T, n(0≤n≤10 000);
以下 n 行每行描述一只蚂蚁的初始位置,其中,整数 x 为蚂蚁距离木棍左端的距离(单位:
厘米),字母表示初始朝向(L 表示朝左,R 表示朝右)

【输出格式】
对于每组数据,输出 n 行,按输入顺序输出每只蚂蚁的位置和朝向(Turning 表示正在
碰撞)。在第 T 秒之前已经掉下木棍的蚂蚁(正好爬到木棍边缘的不算)输出 Fell off

【样例输入】
2
10 1 4
1 R
5 R
3 L
10 R
10 2 3
4 R
5 L
8 R
【样例输出】
Case #1:
2 Turning
6 R
2 Turning
Fell off
Case #2:
3 L
6 R
10 R

【分析】

假设你在远处观察这些蚂蚁的运动,会看到什么?一群密密麻麻的小黑点在移动

由于黑点太小,所以蚂蚁因碰撞而掉头时,看上去和两个点“对穿而过”没有任何区别,换句话说,如果把蚂蚁看成是没有区别的小点,那么只需要独立计算出每只蚂蚁在 T 时刻的位置即可

比如,有 3 只蚂蚁,蚂蚁 1 = (1, R),蚂蚁 2 = (3, L),蚂蚁 3 = (4, L),则在两秒之后,3 只蚂蚁分别为 (3, R),(1, L) 和 (2, L)

注意,,虽然从整体上讲,“掉头”等价于“对穿而过”,但对于每只蚂蚁而言并不是这样

蚂蚁 1 的初始状态为 (1, R),因此一定有一只蚂蚁在两秒钟之后处于 (3, R) 的状态,但这只蚂蚁却不一定是蚂蚁 1。换句话说,我们需要搞清楚目标状态中“谁是谁”

也许你也已经发现了其中的奥妙:所有蚂蚁的相对顺序是保持不变的

因此把所有目标位置从小到大排序,则从左到右的每个位置对应于初始状态下从左到右的每只蚂蚁

由于原题中蚂蚁不一定按照从左到右的顺序输入,还需要预处理计算出输入中第 i 只蚂蚁的序号 order[i]

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, string> Pair;

const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e4 + 10;
const char dirName[][10] = {"L", "Turning", "R"};

struct Ant {
    int id;     //输入位置
    int pos;      //位置
    int turn;   //朝向 -1:左;0:转身中;1:右
    bool operator < (const Ant& a) const {
        return pos < a.pos;
    }
};

Ant before[maxn], after[maxn];
int L, T, n;
int order[maxn];    //输入的第 i 只蚂蚁是终态中的左数第 order[i] 只蚂蚁

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    int Cases;
    scanf("%d", &Cases);
    for (int i = 1; i <= Cases; ++i) {
        printf("Case #%d:\n", i);
        scanf("%d%d%d", &L, &T, &n);
        int pos, turn;
        char c;
        for (int j = 0; j < n; ++j) {
            scanf("%d %c", &pos, &c);
            turn = (c == 'L' ? -1 : 1);
            before[j] = (Ant){j, pos, turn};
            after[j] = (Ant){0, pos+T*turn, turn};
        }

        //计算 order 数组
        sort(before, before+n);
        for (int j = 0; j < n; ++j) {
            order[before[j].id] = j;
        }

        //计算终态
        sort(after, after+n);
        for (int j = 0; j < n-1; ++j) {
            if (after[j].pos == after[j+1].pos) {
                after[j].turn = after[j+1].turn = 0;
            }
        }

        //输出结果
        for (int j = 0; j < n; ++j) {
            int order_t = order[j];
            if (after[order_t].pos < 0 || after[order_t].pos > L) {
                printf("Fell off\n");
            } else {
                printf("%d %s\n", after[order_t].pos, dirName[after[order_t].turn+1]);
            }
        }
        printf("\n");
    }
    return 0;
}

我的代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, string> Pair;

const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;

int L, T, n;
vector<int> Begin, Begin_t;
vector<Pair> End;
string turn_t;
int pos_t;

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    int Cases;
    scanf("%d", &Cases);
    for (int i = 1; i <= Cases; ++i) {
        Begin.clear(), Begin_t.clear(), End.clear();
        printf("Case #%d:\n", i);
        scanf("%d%d%d", &L, &T, &n);
        for (int j = 0; j < n; ++j) {
            cin >> pos_t >> turn_t;
            Begin.push_back(pos_t), Begin_t.push_back(pos_t);
            if (turn_t == "L") {
                pos_t -= T;
            } else {
                pos_t += T;
            }
            End.push_back(make_pair(pos_t, turn_t));
        }
        sort(Begin_t.begin(), Begin_t.end());
        sort(End.begin(), End.end());
        for (int j = 0; j < n; ++j) {
            if (End[j].first < 0 || End[j].first > L) {
                End[j].first = -1;
            } else if (j > 0 && End[j].first == End[j-1].first) {
                End[j].second = End[j-1].second = "Turning";
            }
        }
        for (int j = 0; j < n; ++j) {
            int pos = lower_bound(Begin_t.begin(), Begin_t.end(), Begin[j]) - Begin_t.begin();
            if (End[pos].first == -1) {
                printf("Fell off\n");
            } else {
                cout << End[pos].first << " " << End[pos].second << endl;
            }
        }
        printf("\n");
    }
    return 0;
}

4、UVALive 2995 Image Is Everything (立方体成像)

题意:

有一个 n×n×n 立方体,其中一些单位立方体已经缺失(剩下部分不一定连通)。每个单位立方体重量为 1 克,且被涂上单一的颜色(即 6 个面的颜色相同)

给出前、左、后、右、顶、底 6 个视图,你的任务是判断这个物体剩下的最大重量

【输入格式】
输入包含多组数据。每组数据的第一行为一个整数 n(1≤n≤10);

以下 n 行每行从左到右依次为前、左、后、右、顶、底 6 个视图每个视图占 n 列,相邻视图中间以一个空格隔开

顶视图的下边界对应于前视图的上边界;底视图的上边界对应于前视图的下边界
在视图中,大写字母表示颜色(不同字母表示不同颜色),句号(.)表示该位置可以看穿(即没有任何立方体)

输入结束标志为 n = 0

【输出格式】
对于每组数据,输出一行,即物体的最大重量(单位:克)

【样例输入】
3
.R. YYR .Y. RYY .Y. .R.
GRB YGR BYG RBY GYB GRB
.R. YRR .Y. RRY .R. .Y.
2
ZZ ZZ ZZ ZZ ZZ ZZ
ZZ ZZ ZZ ZZ ZZ ZZ
0
【样例输出】
Maximum weight: 11 gram(s)
Maximum weight: 8 gram(s)
【分析】
这个问题看上去有点棘手,不过仍然可以找到突破口

比如,能“看穿”的位置所对应的所有单位立方体一定都不存在

再比如,如果前视图的右上角颜色 A 和顶视图右下角的颜色 B 不同,那么对应的格子一定不存在,如图所示


在删除这个立方体之后,我们可能会有新发现:

C 和 D 的颜色不同

这样,我们又能删除一个新的立方体,并暴露出新的表面。当无法继续删除的时候,剩下的立方体就是重量最大的物体


解释如下:

首先不难证明第一次删除是必要的(即被删除的那个立方体不可能存在于任意可行解中),因为只要不删除这个立方体,对应两个视图的“矛盾”将一直存在

接下来,我们用数学归纳法,假设算法的前 k 次删除都是必要的,那么第 k+1 次删除是否也是必要的呢?

由刚才的推理,我们不能继续删除立方体来消除矛盾,而由归纳假设,已经删除的立方体也不能恢复,因此矛盾无法消除

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>

using namespace std;

#define REP(i, n) for (int i = 0; i < n; ++i)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const ull mod = 1e9 + 7;
const int InF = 0x7fffffff;
int n;
char view[10][20][20];
char cube[20][20][20];

char read_char(void);
void get_coordinate(int k, int i, int j, int p, int &x, int &y, int &z);

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    while (scanf("%d", &n) != EOF && n != 0) {
        REP(i, n) REP(k, 6) REP(j, n) {
            view[k][i][j] = read_char();
        }
        memset(cube, '#', sizeof(cube));
        REP(k, 6) REP(i, n) REP(j, n) {
            if (view[k][i][j] == '.') {
                REP(p, n) {
                    int x, y, z;
                    get_coordinate(k, i, j, p, x, y, z);
                    cube[x][y][z] = '.';
                }
            }
        }
        while (1) {
            bool flag = true;
            REP(k, 6) REP(i, n) REP(j, n) {
                if (view[k][i][j] != '.') {
                    REP(p, n) {
                        int x, y, z;
                        get_coordinate(k, i, j, p, x, y, z);
                        if (cube[x][y][z] == '.') {
                            continue;
                        }
                        if (cube[x][y][z] == '#') {
                            cube[x][y][z] = view[k][i][j];
                            break;
                        }
                        if (cube[x][y][z] == view[k][i][j]) {
                            break;
                        }
                        cube[x][y][z] = '.';
                        flag = false;
                    }
                }
            }
            if (flag) {
                break;
            }
        }
        int ans = 0;
        REP(i, n) REP(j, n) REP(k, n) {
            if (cube[i][j][k] != '.') {
                ++ans;
            }
        }
        printf("Maximum weight: %d gram(s)\n", ans);
    }
    return 0;
}

char read_char(void)
{
    char c;
    while (1) {
        c = getchar();
        if (isupper(c) || c == '.') {
            return c;
        }
    }
}

void get_coordinate(int k, int i, int j, int p, int &x, int &y, int &z)
{
    if (k == 0) {
        x = p, y = j, z = i;
    } else if (k == 1) {
        x = n-1 - j, y = p, z = i;
    } else if (k == 2) {
        x = n-1 - p, y = n-1 - j, z = i;
    } else if (k == 3) {
        x = j, y = n-1 - p, z = i;
    } else if (k == 4) {
        x = n-1 - i, y = j, z = p;
    } else {
        x = i, y = j, z = n-1 - p;
    }
}

5、UVa 11464 Even Parity (偶数矩阵)

题意:

给你一个 n×n 的 01 矩阵(每个元素非 0 即 1),你的任务是把尽量少的 0 变成 1,使得每个元素的上、下、左、右的元素(如果存在的话)之和均为偶数

比如,如图(a)所示的矩阵至少要把 3 个 0 变成 1,最终如图(b)所示,才能保证其为偶数矩阵


【输入格式】
输入的第一行为数据组数 T(T≤30)。每组数据的第一行为正整数 n(1 ≤ n ≤ 15)
接下来的 n 行每行包含 n 个非 0 即 1 的整数,相邻整数间用一个空格隔开

【输出格式】
对于每组数据,输出被改变的元素的最小个数。如果无解,应输出 -1
【分析】
也许最容易想到的方法就是枚举每个数字“变”还是“不变”,最后判断整个矩阵是否满足条件

遗憾的是,这样最多需要枚举 2^225 ≈ 5 * 10^67 种情况,实在难以承受


注意到 n 只有 15,第一行只有不超过 2^15 = 32768 种可能,所以第一行的情况是可以枚举的

接下来根据第一行可以完全计算出第二行,根据第二行又能计算出第三行

以此类推,这样,总时间复杂度即可降为 O(2^n * n^2)


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>

using namespace std;

#define REP(i, n) for (int i = 0; i < (n); ++i)

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 30;
int n;
int G[maxn][maxn], G_t[maxn][maxn];

int check(int x);

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    int T;
    scanf("%d", &T);
    int Cases = 0;
    while (T--) {
        scanf("%d", &n);
        REP(i, n) REP(j, n) {
            scanf("%d", &G[i][j]);
        }
        int ans = INF;
        for (int i = 0; i < (1 << n); ++i) {
            ans = min(ans, check(i));
        }
        if (ans == INF) {
            ans = -1;
        }
        printf("Case %d: %d\n", ++Cases, ans);
    }
    return 0;
}

int check(int x)
{
    memset(G_t, 0, sizeof(G_t));
    for (int i = 0; i < n; ++i) {
        if (x & 1) {
            G_t[0][i] = 1;
        } else if (G[0][i] == 1) {
            return INF;
        }
        x >>= 1;
    }
    for (int r = 1; r < n; ++r) {
        for (int c = 0; c < n; ++c) {
            int sum = 0;    //元素 G_t[r-1][c] 的上、左、右 3 个元素之和
            if (r > 1) {
                sum += G_t[r-2][c];
            }
            if (c > 0) {
                sum += G_t[r-1][c-1];
            }
            if (c < n-1) {
                sum += G_t[r-1][c+1];
            }
            G_t[r][c] = sum%2;
            if (G[r][c] == 1 && G_t[r][c] == 0) {
                return INF;
            }
        }
    }
    int Count = 0;
    REP(r, n) REP(c, n) {
        if (G[r][c] != G_t[r][c]) {
            ++Count;
        }
    }
    return Count;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值