首页 > 试题广场 >

涂色II

[编程题]涂色II
  • 热度指数:117 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
牛牛管理着一片农场,在这片农场的一侧有着 块栅栏排成一排,为了给单调的牧场生活增添一份乐趣,牛牛决定为这 块栅栏涂色。

现在,牛牛在牧场中一共找到了 种不同颜料,每种颜料都有自己的推荐方案,如:第 种颜料罐上写着,在这种颜料后如果紧跟 种颜料中的一个,整体色调就会显得不那么美丽。

那么,在满足上述前提下,牛牛最终完成的美丽的涂色一共会有多少种方案?

由于答案可能很大,所以只需要求出对 取模后的结果。

输入描述:
本题为多组测试数据,第一行输入一个正整数 ,代表测试数据组数。

对于每组测试数据,第一行输入三个正整数 ,代表栅栏总数,颜料总数以及每种颜料后不能紧跟的颜料种类数。
接下去 行,每行输入 个正整数,,代表该种颜料后不能紧跟这 种颜色。


输出描述:
对于每组测试数据,输出一行一个数字表示牛牛的涂色方案。
示例1

输入

1
2 2 1
1
1

输出

2
动态规划
利用一个set记录下个位置不能选的元素,遍历当前位置的颜色,将上个位置的所有方案逐一考虑,若果能选就加上上个位置此方案的数量

时间复杂度:n * m * m
import java.util.*;
public class Main {

        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int T = sc.nextInt();
            for (int i = 0; i < T; i++) {
                int n = sc.nextInt();
                int m = sc.nextInt();
                int k = sc.nextInt();
                // int[][] nums = new int[m + 1][k];
                Map<Integer, Set<Integer>> map = new HashMap<>();
                for (int j = 1; j <= m; j++) {
                    // map.put(j, new HashSet<>());
                    Set<Integer> set = new HashSet<>();
                    for (int t = 0; t < k; t++) {
                        set.add(sc.nextInt());
                    }
                    map.put(j, set);
                }
                System.out.println(plans(n, map));
            }
            sc.close();
        }

        private static int MOD = (int)(Math.pow(10, 9) + 7);

        public static int plans(int n, Map<Integer, Set<Integer>> map) {
            int m = map.size();
            //f表示第i个位置选了j的方案数。
            int[][] f = new int[n + 1][m + 1];
            for (int i = 1; i <= m; i++) { //第一个位置谁都可以选
                f[1][i] = 1;
            }
            for (int i = 2; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    f[i][j] = 0;
                    for (int k = 1; k <= m; k++) {
                        Set<Integer> set = map.get(k);
                        if (!set.contains(j)) {
                            f[i][j] = (f[i][j] + f[i - 1][k]) % MOD;
                        } 
                    }

                }
            }
            int res = 0;
            for (int i = 1; i <= m; i++) {
                res = (f[n][i] + res) % MOD;
            }
            return res;
        }
    }

发表于 2022-03-14 13:20:47 回复(0)

动态规划

  • 状态表示:f[i][j]表示考虑前i个物体, 并将i个物体染成j这种颜色的不同方案数
  • 状态计算: 枚举i - 1位置可以染的所有的颜色, 若颜色k后可以接j, 则f[i][j] += f[i - 1][k]
  • 最终答案: 枚举i从1 - m,ans += f[n][i]

时间复杂度

  • 状态是O(nm)
  • 转移是O(m)
  • 整体时间复杂度为O(nm^2)
// 提交时间:2021-10-18 语言:C++ 运行时间: 27 ms 占用内存:508K 状态:答案正确 #include <bits/stdc++.h>

using namespace std;
const int N = 1010, M = 12, MOD = 1e9 + 7;
int f[N][M];
int nxt[M][M];

void solve(){
    memset(nxt, 0, sizeof(nxt));
    memset(f, 0, sizeof(f));
    int n, m, k;
    cin >> n >> m >> k;

    for (int i = 1; i <= m; i ++ )
        for (int j = 1; j <= k; j ++ ) {
            int x; 
            cin >> x ;
            nxt[i][x] = 1;
        }

    for (int i = 1; i <= m; i ++ )
        f[1][i] = 1;    
    for (int i = 2; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ ) {
            for (int k = 1; k <= m; k ++ )
                if (nxt[k][j] == 0)
                    f[i][j] = (f[i][j] + f[i - 1][k]) % MOD;
        }
    int ans = 0;
    for (int i = 1; i <= m; i ++ )
        ans = (ans + f[n][i]) % MOD;
    ans = (ans + MOD) % MOD;
    cout << ans << '\n';
}

int main()
{   
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin >> t;
    while (t -- )
        solve();
    return 0;
}

编辑于 2021-10-19 10:26:18 回复(0)
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;

public class Main {

    // 贝壳2021开发岗 第四题

    static long modd = 0;

    public static void main(String[] args) {

        modd = (long) Math.pow(10, 9);
        modd += 7;
        Scanner sc = new Scanner(System.in);

        while (sc.hasNext()) {
            int t = sc.nextInt();

            for (int l = 0; l<=t-1; l++) {
                int n = sc.nextInt();
                int m = sc.nextInt();
                int k = sc.nextInt();

                int[][] notFollow = new int[m+1][k];
                long[][] res = new long[m+1][n+1];

                for (int i = 1; i<=m; i++) {
                    for (int j = 0; j<=k-1;j++) {
                        notFollow[i][j] = sc.nextInt();
                    }
                    Arrays.sort(notFollow[i]);
                }

                long finalRes = 0;
                for (int i = 1; i<=n;i++) {
                    if (i == 1) {
                        for (int j = 1; j<=m; j++) {
                            res[j][i] = 1;
                        }
                    } else {
                        for (int j = 1; j<=m; j++) {
                            HashSet<Integer> hs = new HashSet<>();
                            for (int s = 1; s<=m; s++) {
                                hs.add(s);
                            }
                            for (int h = 0; h<=k-1; h++) {
                                hs.remove(notFollow[j][h]);
                            }
                            long sum = 0;
                            for (Integer follow: hs
                                 ) {
                                sum = (sum + (res[follow][i-1] % modd) % modd);
                            }
                            if (i == n) {
                                finalRes = (sum + finalRes) % modd;
                            }
                            res[j][i] = sum;
                        }
                    }
                }

                System.out.println(finalRes % modd);
            }
        }
    }
}

发表于 2021-05-09 21:35:34 回复(0)