В определенной последовательности используются только числа 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];
}
5 ответов
Учтите следующее: пусть 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)
.
mod 1e9+7
.
Ваш код требует условия (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;
}
В следующем подходе используются четырехмерные массивы для хранения количества конкретных последовательностей без смежных.
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 единиц, заканчивающихся на 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;
}
Спасибо за логику, но в ней есть небольшая ошибка. Посмотрите на саму вторую итерацию, когда i = 0, j = 0, k = 0, l = 1: мы имеем d4 [0] [0] [0] [1] = 0. т.е. базовый случай изменяется и, следовательно, ответ будет 0. Быстрое решение этой проблемы может быть выполнено во внутреннем цикле после повторного обновления всех базовых случаев d add 4. Это исправляет. Если у кого-то есть идеи получше, прокомментируйте это.
Вышеупомянутое решение не будет обрабатываться для больших элементов .. это решение будет работать со всеми тестовыми примерами .. Протестировано :)
#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;
}
Похожие вопросы
Новые вопросы
algorithm
Алгоритм - это последовательность четко определенных шагов, которые определяют абстрактное решение проблемы. Используйте этот тег, если ваша проблема связана с дизайном алгоритма.
dp
, который вы инициализировали в цикле. Простой способ решить эту проблему — обновитьdp
, еслиi+j+k+l > 1
.