有一个特定的序列只使用数字1,2,3,4并且没有两个相邻的数字是相同的 编写一个给出n1 1s,n2 2s,n3 3s,n4 4s的程序将使用所有这些数字输出这些序列的数量。
输出您的答案模1000000007(10 ^ 9 + 7)。
我在geeksforgeeks.com上发现了这个问题。
打印所有此类解决方案的天真方法将花费O(4 ^ n)。使用动态编程可以有更好的解决方案吗?
我尝试为DP运行以下代码。给出了错误的答案。有人可以建议改进吗?
#include<iostream>
using namespace std;
int d1[50][50][50][50],d2[50][50][50][50],d3[50][50][50][50],d4[50][50][50][50];
int main(){
int n1,n2,n3,n4;
n1=2;n2=2;n3=1;n4=2;
d1[1][0][0][0]=1;
d2[0][1][0][0]=1;
d3[0][0][1][0]=1;
d4[0][0][0][1]=1;
for(int i=0;i<=n1;i++){
for(int j=0;j<=n2;j++){
for(int k=0;k<=n3;k++){
for(int l=0;l<=n4;l++){
if(i)d1[i][j][k][l]=d2[i-1][j][k][l]+d3[i-1][j][k][l]+d4[i-1][j][k][l];
if(j)d2[i][j][k][l]=d1[i][j-1][k][l]+d3[i][j-1][k][l]+d4[i][j-1][k][l];
if(k)d3[i][j][k][l]=d2[i][j][k-1][l]+d1[i][j][k-1][l]+d4[i][j][k-1][l];
if(l)d4[i][j][k][l]=d2[i][j][k][l-1]+d3[i][j][k][l-1]+d1[i][j][k][l-1];
}
}
}
}
cout<<d1[n1][n2][n3][n4]+d2[n1][n2][n3][n4]+d3[n1][n2][n3][n4]+d4[n1][n2][n3][n4];
}
答案 0 :(得分:3)
请考虑以下事项:
让dpX[i][j][k][l]
代表以X
结尾的此类序列的数量,X
为1,2,3或4,i
个,j
两个, k
三分,l
四肢。然后,您将获得dp1
的公式:
dp1[i][j][k][l] = dp2[i-1][j][k][l] + dp3[i-1][j][k][l] + dp4[i-1][j][k][l]
类似于dp2
,dp3
和dp4
。答案是dp1[n1][n2][n3][n4] +
dp2[n1][n2][n3][n4] + dp3[n1][n2][n3][n4] + dp4[n1][n2][n3][n4]
。
时间复杂度为O(n1*n2*n3*n4)
。
答案 1 :(得分:3)
您的代码需要条件(i + j + k + l> 1)否则它会生成 dp4 [0] [0] [0] [1] = 0.这也适用于其他dpX。
#include<bits/stdc++.h>
using namespace std;
int d1[50][50][50][50],d2[50][50][50][50],d3[50][50][50][50],d4[50][50][50][50];
#define MOD 1000000007
int main(){
int n1,n2,n3,n4;
scanf("%d%d%d%d", &n1, &n2, &n3, &n4);
d1[1][0][0][0]=1;
d2[0][1][0][0]=1;
d3[0][0][1][0]=1;
d4[0][0][0][1]=1;
for(int i=0;i<=n1;i++){
for(int j=0;j<=n2;j++){
for(int k=0;k<=n3;k++){
for(int l=0;l<=n4;l++){
if (i + j + k + l > 1) {
if(i)d1[i][j][k][l]=d2[i-1][j][k][l]+d3[i-1][j][k][l]+d4[i-1][j][k][l] % MOD;
if(j)d2[i][j][k][l]=d1[i][j-1][k][l]+d3[i][j-1][k][l]+d4[i][j-1][k][l] % MOD;
if(k)d3[i][j][k][l]=d2[i][j][k-1][l]+d1[i][j][k-1][l]+d4[i][j][k-1][l] % MOD;
if(l)d4[i][j][k][l]=d2[i][j][k][l-1]+d3[i][j][k][l-1]+d1[i][j][k][l-1] % MOD;
}
}
}
}
}
cout<<d1[n1][n2][n3][n4]+d2[n1][n2][n3][n4]+d3[n1][n2][n3][n4]+d4[n1][n2][n3][n4] % MOD << endl;
}
答案 2 :(得分:1)
以下方法使用4维数组来存储没有相邻的特定序列的数量。
dp1 [i] [j] [k] [l]:没有相邻末端的特定序列的数量为1且具有i 1s,j 2s,k 3s,l 4s。
dp2 [i] [j] [k] [l]:没有相邻末端的特定序列的数量为2,并且具有i 1s,j 2s,k 3s,l 4s。
所以dp1 [i] [j] [k] [l] = dp2 [i - 1] [j] [k] [l] + dp3 [i - 1] [j] [k] [l] + dp4 [i - 1] [j] [k] [l];
dp1将是i - 1 1s与2(dp2),3(dp3),4(dp4)结束的总和;
public int Sequence(int n1, int n2, int n3, int n4)
{
var dp1 = new int[n1 + 1, n2 + 1, n3 + 1, n4 + 1];
var dp2 = new int[n1 + 1, n2 + 1, n3 + 1, n4 + 1];
var dp3 = new int[n1 + 1, n2 + 1, n3 + 1, n4 + 1];
var dp4 = new int[n1 + 1, n2 + 1, n3 + 1, n4 + 1];
const int MOD = 1000000007;
dp1[1, 0, 0, 0] = 1;
dp2[0, 1, 0, 0] = 1;
dp3[0, 0, 1, 0] = 1;
dp4[0, 0, 0, 1] = 1;
for (int i = 0; i <= n1; i++)
{
for (int j = 0; j <= n2; j++)
{
for (int k = 0; k <= n3; k++)
{
for (int l = 0; l <= n4; l++) {
if (i + j + k + l > 1)
{
if (i > 0) dp1[i, j, k, l] = dp2[i - 1, j, k, l] + dp3[i - 1, j, k, l] + dp4[i - 1, j, k, l] % MOD;
if (j > 0) dp2[i, j, k, l] = dp1[i, j - 1, k, l] + dp3[i, j - 1, k, l] + dp4[i, j - 1, k, l] % MOD;
if (k > 0) dp3[i, j, k, l] = dp2[i, j, k - 1, l] + dp1[i, j, k - 1, l] + dp4[i, j, k - 1, l] % MOD;
if (l > 0) dp4[i, j, k, l] = dp2[i, j, k, l - 1] + dp3[i, j, k, l - 1] + dp1[i, j, k, l - 1] % MOD;
}
}
}
}
}
return dp1[n1, n2, n3, n4] + dp2[n1, n2, n3, n4] + dp3[n1, n2, n3, n4] + dp4[n1, n2, n3, n4] % MOD;
}
答案 3 :(得分:0)
感谢您的逻辑,但它有一个小错误。当i = 0,j = 0,k = 0,l = 1时,查看第二次迭代本身:我们有d4 [0] [0] [0] [1] = 0.即,基本情况正在被修改,因此答案变为0.这个问题的快速修复可能是在更新所有d再次添加4个基本案例后的最内层循环中。这解决了它。如果有人有任何更好的想法,请对其进行评论。
答案 4 :(得分:0)
以上解决方案不会处理大元素..这个解决方案将适用于所有测试用例。经过测试:)
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
int d1[21][21][21][21],d2[21][21][21][21],d3[21][21][21][21],d4[21][21][21][21];
#define MOD 1000000007
int main(){
ll n1,n2,n3,n4;
cin>>n1>>n2>>n3>>n4;
d1[1][0][0][0]=1;
d2[0][1][0][0]=1;
d3[0][0][1][0]=1;
d4[0][0][0][1]=1;
for(int i=0;i<=n1;i++){
for(int j=0;j<=n2;j++){
for(int k=0;k<=n3;k++){
for(int l=0;l<=n4;l++){
if (i + j + k + l > 1) {
if(i>0)d1[i][j][k][l]=(d2[i-1][j][k][l] % MOD +d3[i-1][j][k][l]% MOD+d4[i-1][j][k][l]% MOD) % MOD;
if(j>0)d2[i][j][k][l]=(d1[i][j-1][k][l] % MOD+d3[i][j-1][k][l]% MOD+d4[i][j-1][k][l]% MOD )% MOD;
if(k>0)d3[i][j][k][l]=(d2[i][j][k-1][l] % MOD+d1[i][j][k-1][l] % MOD+d4[i][j][k-1][l]% MOD) % MOD;
if(l>0)d4[i][j][k][l]=(d2[i][j][k][l-1] % MOD+d3[i][j][k][l-1] % MOD+d1[i][j][k][l-1]% MOD) % MOD;
}
}
}
}
}
cout<<(d1[n1][n2][n3][n4]% MOD+d2[n1][n2][n3][n4]% MOD+d3[n1][n2][n3][n4]% MOD+d4[n1][n2][n3][n4]% MOD) % MOD << endl;
}