백준 23816번 옷걸이걸이걸이 문제풀이 c++
백준 23816번 옷걸이걸이걸이
https://www.acmicpc.net/problem/23816
23816번: 옷걸이걸이걸이
차례대로 높이가 1, 2, 2, 3인 옷걸이 트리를 놓으면 각각에 옷을 1, 2, 2, 4개 걸 수 있다.
www.acmicpc.net
문제 해석
문제를 자세히 읽어보면 남는 옷걸이를 둘데가 없으므로 모든 옷걸이를 옷장 속으로 넣어야 하고
옷장에 자리 하나당 옷걸이 트리하나를 걸수가 있다.
옷걸이 트리는 높이가 1,2,3,4는 넣을 수 있고
높이가 1인 트리를 넣으면 걸 수있는 옷의 수는 1개,필요한 옷걸이수는 1개
높이가 2인 트리를 넣으면 걸 수있는 옷의 수는 2개,필요한 옷걸이수는 3개
높이가 3인 트리를 넣으면 걸 수있는 옷의 수는 4개,필요한 옷걸이수는 7개
높이가 4인 트리를 넣으면 걸 수있는 옷의 수는 0개,필요한 옷걸이수는 15개 이다.
그렇다면 dp[i][j]의 정의를 옷장의 남은공간이 i개 남은 옷걸이 수가 j개라고 할때의 걸 수있는 옷의 수로 정의를한다면
dp[i][j]=max({dp[i-1][j-15],4+dp[i-1][j-7],2+dp[i-1][j-3],1+dp[i-1][j-1]}) 이다.
i=0, 1<=j 일때 (즉, 옷장에 자리가없고 옷걸이가 남아있을때) dp[i][j]=-1
i=1일때 j=1,3,7,15를 제외한 dp[i][j]=-1 dp[1][1]=1 , dp[1][3]=2 , dp[1][7]=4 ,d p[1][15]=0
초기 설정은 위와 같고 i=2, j=1 부터 위의 점화식을 적용해주면 된다.
코드
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int dp[5001][10001];
int n,m;
int main(){
cin.tie(NULL);
cout.tie(NULL);
ios_base::sync_with_stdio(false);
cin>>n>>m;
for(int i=1; i<10001; i++)
{
dp[0][i]=-1;
dp[1][i]=-1;
}
dp[1][1]=1;
dp[1][3]=2;
dp[1][7]=4;
dp[1][15]=0;
for(int i=2; i<5001; i++)
{
for(int j=1; j<10001; j++)
{
if(1<=j&&j<3)
{
if(dp[i-1][j-1]!=-1)
{
dp[i][j]=1+dp[i-1][j-1];
}
else
{
dp[i][j]=-1;
}
}
else if(3<=j&&j<7)
{
if(dp[i-1][j-3]!=-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max(2+dp[i-1][j-3],1+dp[i-1][j-1]);
}
else if(dp[i-1][j-3]==-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=1+dp[i-1][j-1];
}
else if(dp[i-1][j-3]!=-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=2+dp[i-1][j-3];
}
else if(dp[i-1][j-3]==-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=-1;
}
}
else if(7<=j&&j<15)
{
if(dp[i-1][j-7]!=-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max({4+dp[i-1][j-7],2+dp[i-1][j-3],1+dp[i-1][j-1]});
}
else if(dp[i-1][j-7]==-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max(2+dp[i-1][j-3],1+dp[i-1][j-1]);
}
else if(dp[i-1][j-7]!=-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max(4+dp[i-1][j-7],1+dp[i-1][j-1]);
}
else if(dp[i-1][j-7]!=-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=max(4+dp[i-1][j-7],2+dp[i-1][j-3]);
}
else if(dp[i-1][j-7]==-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=dp[i-1][j-1];
}
else if(dp[i-1][j-7]==-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=2+dp[i-1][j-3];
}
else if(dp[i-1][j-7]!=-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=4+dp[i-1][j-7];
}
else if(dp[i-1][j-7]==-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=-1;
}
}
else if(15<=j)
{
if(dp[i-1][j-15]!=-1&&dp[i-1][j-7]!=-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max({dp[i-1][j-15],4+dp[i-1][j-7],2+dp[i-1][j-3],1+dp[i-1][j-1]});
}
else if(dp[i-1][j-15]==-1&&dp[i-1][j-7]!=-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max({4+dp[i-1][j-7],2+dp[i-1][j-3],1+dp[i-1][j-1]});
}
else if(dp[i-1][j-15]!=-1&&dp[i-1][j-7]==-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max({dp[i-1][j-15],2+dp[i-1][j-3],1+dp[i-1][j-1]});
}
else if(dp[i-1][j-15]!=-1&&dp[i-1][j-7]!=-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max({dp[i-1][j-15],4+dp[i-1][j-7],1+dp[i-1][j-1]});
}
else if(dp[i-1][j-15]!=-1&&dp[i-1][j-7]!=-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=max({dp[i-1][j-15],4+dp[i-1][j-7],2+dp[i-1][j-3]});
}
else if(dp[i-1][j-15]==-1&&dp[i-1][j-7]==-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max(2+dp[i-1][j-3],1+dp[i-1][j-1]);
}
else if(dp[i-1][j-15]==-1&&dp[i-1][j-7]!=-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max(4+dp[i-1][j-7],1+dp[i-1][j-1]);
}
else if(dp[i-1][j-15]==-1&&dp[i-1][j-7]!=-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=max(4+dp[i-1][j-7],2+dp[i-1][j-3]);
}
else if(dp[i-1][j-15]!=-1&&dp[i-1][j-7]==-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=max(dp[i-1][j-15],1+dp[i-1][j-1]);
}
else if(dp[i-1][j-15]!=-1&&dp[i-1][j-7]==-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=max(dp[i-1][j-15],2+dp[i-1][j-3]);
}
else if(dp[i-1][j-15]!=-1&&dp[i-1][j-7]!=-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=max(dp[i-1][j-15],4+dp[i-1][j-7]);
}
else if(dp[i-1][j-15]==-1&&dp[i-1][j-7]==-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]!=-1)
{
dp[i][j]=1+dp[i-1][j-1];
}
else if(dp[i-1][j-15]==-1&&dp[i-1][j-7]==-1&&dp[i-1][j-3]!=-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=2+dp[i-1][j-3];
}
else if(dp[i-1][j-15]==-1&&dp[i-1][j-7]!=-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=4+dp[i-1][j-7];
}
else if(dp[i-1][j-15]!=-1&&dp[i-1][j-7]==-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=dp[i-1][j-15];
}
else if(dp[i-1][j-15]==-1&&dp[i-1][j-7]==-1&&dp[i-1][j-3]==-1&&dp[i-1][j-1]==-1)
{
dp[i][j]=-1;
}
}
}
}
cout<<dp[n][m]<<"\n";
}
여기서 중요한게 있는데 dp[i][j]=max({dp[i-1][j-15],4+dp[i-1][j-7],2+dp[i-1][j-3],1+dp[i-1][j-1]})를 생각없이 넣어버리면 안된다.
만약 max속에 4개 인자 dp[i-1][j-15] , dp[i-1][j-7] , dp[i-1][j-3] , dp[i-1][j-1] 중
값이 -1인것이 있으면 그건 후보에서 제외한 후에 max를 사용해야한다.
만약 4개 전부 -1이면 dp[i][j]는 -1의 값을 가져야한다.
이 부분 처리를 간결하게 어떻게 해야할지 모르겠어서 j범위에 따라 각각 2,4,8,16가지 경우를 모두써서 제출해서 맞긴했는데 눈이 너무 아팠다....