P1541 [NOIP2010 提高组] 乌龟棋(dp)dp5

//https://www.luogu.com.cn/problem/P1541
#include<bits/stdc++.h>
#include<unordered_map>
#include<array>
#define ll long long
#define ull unsigned long long
#define all(a) a.begin(),a.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;

const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;
const ll mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, m, num[5], dp[5][41][41][41][41], a[N];//dp一维表示位置, 因为太大开不下, 则开滚动数组来记录,因为只会从前面四个进行转移 

void solve()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1, x; i <= m; i++)
		cin >> x, num[x]++;//存储每张牌的数量

	int ans = 0;
	for (int now = 2; now <= n; now++)//枚举当前位置, 当前位置可从少一张牌的情况转移过来
	{
		for (int i = 0; i <= num[1]; i++)
		{
			for (int j = 0; j <= num[2]; j++)
			{
				for (int k = 0; k <= num[3]; k++)
				{
					for (int l = 0; l <= num[4]; l++)
					{
						if (i + 2 * j + 3 * k + 4 * l == now - 1)
						{
							if (now >= 2 && i)
								dp[(now - 1) % 5][i][j][k][l] = max(dp[(now - 1) % 5][i][j][k][l], dp[(now - 2) % 5][i - 1][j][k][l] + a[now]);
							if(now >= 3 && j)
								dp[(now - 1) % 5][i][j][k][l] = max(dp[(now - 1) % 5][i][j][k][l], dp[(now - 3) % 5][i][j - 1][k][l] + a[now]);
							if(now >= 4 && k)
								dp[(now - 1) % 5][i][j][k][l] = max(dp[(now - 1) % 5][i][j][k][l], dp[(now - 4) % 5][i][j][k - 1][l] + a[now]);
							if(now >= 5 && l)
								dp[(now - 1) % 5][i][j][k][l] = max(dp[(now - 1) % 5][i][j][k][l], dp[(now - 5) % 5][i][j][k][l - 1] + a[now]);
							ans = max(ans, dp[(now - 1) % 5][i][j][k][l]);
						}
					}
				}
			}
		}
	}
	cout << ans + a[1] << '\n';
}

signed main()
{
	IOS;
	int t = 1;
	//cin >> t;
	while (t--)
		solve();
	return 0;
}

#include<bits/stdc++.h>
#include<unordered_map>
#include<array>
#define ll long long
#define ull unsigned long long
#define all(a) a.begin(),a.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;

const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;
const ll mod = 1e9 + 7;
const int N = 1e5 + 5;

int n, m, num[5], dp[41][41][41][41], a[N];

void solve()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1, x; i <= m; i++)
		cin >> x, num[x]++;//存储每张牌的数量

	int ans = 0;
	for (int i = 0; i <= num[1]; i++)//每组i, j, k, l对于唯一的now, 所以无需枚举now, 转移只是根据牌数而非位置(b 位置要从 a 位置转移过来, 只会选择一种牌少一张的转移方式)
	{
		for (int j = 0; j <= num[2]; j++)
		{
			for (int k = 0; k <= num[3]; k++)
			{
				for (int l = 0; l <= num[4]; l++)
				{
					int now = 1 + i + 2 * j + 3 * k + 4 * l;
					if (now > n)
						continue;
					if (i)
						dp[i][j][k][l] = max(dp[i][j][k][l], dp[i - 1][j][k][l] + a[now]);
					if (j)
						dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j - 1][k][l] + a[now]);
					if (k)
						dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j][k - 1][l] + a[now]);
					if (l)
						dp[i][j][k][l] = max(dp[i][j][k][l], dp[i][j][k][l - 1] + a[now]);
					ans = max(ans, dp[i][j][k][l]);
				}
			}
		}
	}
	cout << ans + a[1] << '\n';
}

signed main()
{
	IOS;
	int t = 1;
	//cin >> t;
	while (t--)
		solve();
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值