算法思维训练之贪心博弈、线性DP详解及实战演练 (2月23日)

128 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划·2月更文挑战」的第18天,点击查看活动详情

Codeforces 1472 D - Even-Odd Game(贪心思想,博弈)

题意:

Alice和Bob在数组a中的n个整数,选择数字

Alice如果选择偶数,那么将这个数字加到Alice的得分中,如果选择了奇数,则不计分

Bob如果选择奇数,那么将这个数字加到Bob的的分钟,如果选择了偶数,则不计分

两者皆采取最优策略,Alice先走,得分多者获胜,如果是平局则输出Tie。

题解:

两者都是最优策略,所谓最优策略就是,判断 我方得分的最大值与对方得分的最大值 的大小,如果我方得分最大值 小于 对方得分的最大值,自然是先把对方的拿掉,反之先拿自己的,让自己加分。

那么让这个序列从大到小排序,Alice先拿,那么序列下标是1~n的,那么:

  • 如果是序列下标为奇数,那么就是Alice拿,如果当前数字是偶数,那么就将该数字加到得分,如果当前数字是奇数,不做任何操作。
  • 如果是序列下标为偶数,那么就是Bob拿,如果当前数字是奇数,那么就将该数字加到得分,如果当前数字是偶数,不做任何操作。
const int N = 200010;
int a[N];
signed main() {
	int t, cin >> t;
	while (t--) {
		int n, cin >> n;
		for (int i = 1; i <= n; i++) cin >> a[i];
		sort(a + 1, a + n + 1, cmp);   //从大到小排序
		int Alice = 0, Bob = 0;
		for (int i = 1; i <= n; i++) {
			if (i % 2 && a[i] % 2 == 0) Alice += a[i];//偶数就加进去 
			else if (a[i] % 2) Bob += a[i];//奇数就加进去 
		}
		if (Alice > Bob) printf("Alice\n");
		else if (Alice < Bob) printf("Bob\n");
		else printf("Tie\n");
	}
	return 0;
}

POJ 2279 杨老师的照相排列 (线性DP)

image.png

image.png

image.png

求合影的方案数?

注意题目范围:k ≤ 5,那么可以最多有5排

开个五维数组 f[a1][a2][a3][a4][a5]f[a_1][a_2][a_3][a_4][a_5] 表示每行分别站了 a1  a2  a3  a4  a5a_1\; a_2 \;a_3\; a_4 \;a_5 个人的方案数,各个维度均满足线性增长的形式。

当安排一名新的学生时:

  1. aiNia_i <N_i
  2. i==1    or    ai1>aii == 1\;\; or\;\; a_{i - 1} > a_i 前面一行的数量要大于当前行的数量

初始化边界:f[0][0][0][0][0]=1;f[0][0][0][0][0] = 1;

const int M = 31;
ll f[M][M][M][M][M];
int s[6];
int main() {
    int k;
    while (cin >> k && k) {
        memset(s, 0, sizeof s);
        for (int i = 1; i <= k; i++) cin >> s[i];
        memset(f, 0, sizeof f);
        f[0][0][0][0][0] = 1;                                     //初始化边界
        for (int a1 = 0; a1 <= s[1]; a1++) {                      //状态转移:
            for (int a2 = 0; a2 <= s[2]; a2++) {
                for (int a3 = 0; a3 <= s[3]; a3++) {
                	for (int a4 = 0; a4 <= s[4]; a4++) {
                        for (int a5 = 0; a5 <= s[5]; a5++) {
                            if (f[a1][a2][a3][a4][a5] == 0) continue;
                            if (a1 < s[1]) f[a1 + 1][a2][a3][a4][a5] += f[a1][a2][a3][a4][a5];
                            if (a2 < s[2] && a1 > a2) f[a1][a2 + 1][a3][a4][a5] += f[a1][a2][a3][a4][a5];
                            if (a3 < s[3] && a2 > a3) f[a1][a2][a3 + 1][a4][a5] += f[a1][a2][a3][a4][a5];
                            if (a4 < s[4] && a3 > a4) f[a1][a2][a3][a4 + 1][a5] += f[a1][a2][a3][a4][a5];
                            if (a5 < s[5] && a4 > a5) f[a1][a2][a3][a4][a5 + 1] += f[a1][a2][a3][a4][a5];
                        }
                	}
                }
            }
        }
        cout << f[s[1]][s[2]][s[3]][s[4]][s[5]] << endl;
    }
    return 0;
}