acwing第80场周赛

比赛地址
核心思路:这是一眼暴力搜索题,但是我们怎么取构造他们的参数呢。首先我们肯定需要4和7的个数,所以这两个参数是肯定需要的,还有就是我们需要他们两个个数加起来不能够大于我们的目标字符串的长度,所以我们也需要一个u。在然后加入我们的搜索的字符串就好了。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
char s[N];
string ans, num;
void dfs(string str, int u, int s4, int s7)//这里的u表示遍历到第几层了
{
	if (u == num.size())
	{
		if (str >= num && (ans.empty() || ans > str))
			ans = str;
		return;
	}
	if (s4 < num.size()  /2)//注意这里是不可以取等号的,还加一就不平衡了
	{
		dfs(str + '4', u + 1, s4 + 1, s7);
	}
	if (s7 < num.size() / 2)
		dfs(str + '7', u + 1, s4, s7 + 1);
}
int main()
{
cin >> num;

    if (num.size() % 2) num = '0' + num;

    dfs("", 0, 0, 0);

    if (ans.empty())
    {
        num = "00" + num;//注意我们这里是往字符串前面加0.例如9999
        dfs("", 0, 0, 0);
    }

    cout << ans << endl;

    return 0;
}

核心思路:刚开始我以为是组合数问题,没想到居然是dp问题。

  1. 集合定义:dp[i][j][k][u]为摆放了i个白子,j个黑子,最后一段连续的黑子数目k和连续的白字数目是u。

  2. 集合划分:其实我们可以发现这个集合不太好划分,所以我们就需要想怎么去转移呢。因为dp问题其实是可以看作最短路的。所以我们需要注意我们这个状态可以转移到什么其他状态就可以了。

  3. 状态转移方程:dp[i+1][j][k+1][0]+=dp[i][j][k][u].

dp[i][j+1][0][u+1]+=dp[i][j][k][u].

代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 110, M = 11, MOD = 1e8;

int n1, n2, k1, k2;
int f[N][N][M][M];
int main()
{
	cin >> n1 >> n2 >> k1 >> k2;
	f[0][0][0][0] = 1;//不摆放也是一种方案.
	for(int i=0;i<=n1;i++)
		for(int j=0;j<=n2;j++)
			for(int k=0;k<=k1;k++)
				for (int u = 0;u <= k2;u++)
				{
					int v = f[i][j][k][u];
					if (i + 1 <= n1 && k + 1 <= k1)
						f[i + 1][j][k + 1][0] = (f[i + 1][j][k + 1][0] + v) % MOD;//为什么是0呢,一定要注意我们的那个定义
					if (j + 1 <= n2 && u + 1 <= k2)
						f[i][j + 1][0][u + 1] = (f[i][j + 1][0][u + 1] + v) % MOD;
				}
	int res = 0;
	for (int i = 0;i <= k1;i++)
		for (int j = 0;j <= k2;j++)
			res = (res + f[n1][n2][i][j]) % MOD;
	cout << res << endl;

}
posted @ 2022-12-04 09:27  努力的德华  阅读(28)  评论(0)    收藏  举报