LED Display(二分图 + 最小路径覆盖)

LED Display

Time Limit: 2 Seconds      Memory Limit: 65536 KB

One day in the laboratory, Fred found some LED displays. This seven-segment LED can display digit 0 to 9 properly. But Fred soon find the LED have a serious problem, at the beginning, the seven bars were all on. But when one bar once was trun off, it can't be turn on again! So ecah LED only can display digit in certain oder. For example, one LED can display 9,3,7 successively, but can't display 2,4.

Now, Fred have a task to display a sequence of digit that is between 0 to 9. Because of the shortcoming of these LEDs, he need a number of them. But he also want to minimize the number, can you help him?

NOTE:If two digits in a sequece are the same,Fred want for the clearness, so he thought the latter digit can't be displayed on the same LED.

Input:

The input consists of several test cases. The first line of each test case contains a positive integer N (<=1000), then followed by a list of N digits. Each digit follows with a blank space.

Output:

For each test case, you must print a minimum number of LED that Fred need in one line.

Sample Input:

1
8

4
9 0 7 3

8
8 8 8 9 6 5 4 1

Sample Output:

1
2		(Hint:one mothod is display {9,3} on the first LED; {0,7} on the second)
3		(Hint:one possible solution is {8},{8,9,4,1},{8,6,5})

 

       题意:

       给出 N (1 ~ 1000),代表有 N 个数,后给出这 N 个数是什么。0 ~ 9 中的某些数字灭了其中的一些 LED 灯能够显示成其他的数字,但是不能显示相同的数字,问需要最少多少个数字,能显示给出的所有 N 个数。

 

       思路:

       二分图 + 最小路径覆盖。将每个数字可以到达的下一个数化成一条条路径,不能到达则说明自己是一条路径,建成一个无环有向图,最后 N - 最大匹配既是答案。

 

       AC:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAX = 1005;

int n;
int num[MAX], Map[MAX][MAX];
int linker[MAX], vis[MAX];

void build() {
    memset(Map, 0, sizeof(Map));

    for (int i = 1; i < n; ++i) {
        for (int j = i + 1; j <= n; ++j) {
            if (num[i] == 0) {
                if (num[j] == 1) Map[i][j] = 1;
                if (num[j] == 7) Map[i][j] = 1;
            } else if (num[i] == 3) {
                if (num[j] == 1) Map[i][j] = 1;
                if (num[j] == 7) Map[i][j] = 1;
            } else if (num[i] == 4) {
                if (num[j] == 1) Map[i][j] = 1;
            } else if (num[i] == 6) {
                if (num[j] == 5) Map[i][j] = 1;
            } else if (num[i] == 7) {
                if (num[j] == 1) Map[i][j] = 1;
            } else if (num[i] == 8 &&
                       num[j] != 8) Map[i][j] = 1;
            else if (num[i] == 9) {
                if (num[j] == 1) Map[i][j] = 1;
                if (num[j] == 3) Map[i][j] = 1;
                if (num[j] == 4) Map[i][j] = 1;
                if (num[j] == 5) Map[i][j] = 1;
                if (num[j] == 7) Map[i][j] = 1;
            }
        }
    }
}

bool dfs (int u) {
    for (int v = 1; v <= n; ++v) {
        if (Map[u][v] && !vis[v]) {
            vis[v] = 1;
            if (linker[v] == -1 || dfs(linker[v])) {
                linker[v] = u;
                return true;
            }
        }
    }

    return false;
}

int hungary () {
    int res = 0;
    memset(linker, -1, sizeof(linker));

    for (int u = 1; u <= n; ++u) {
        memset(vis, 0, sizeof(vis));
        if (dfs(u)) ++res;
    }

    return res;
}

int main() {

    while(~scanf("%d", &n)) {

        for (int i = 1; i <= n; ++i)
            scanf("%d", &num[i]);

        build();

        printf("%d\n", n - hungary());
    }

    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值