P1220 가로등 끄기(구간dp)
상태 방정식 dp[j][i][0]=min(dp[j+1][i][0]+(x[j+1]-x[j])*(sum[n]-(sum[i]-sum[j]), dp[j+1][i][1]+(x[i]-x[j])*(sum[n]-(sum[i]-sum[j]))))
와 dp[j][i][1]=min(dp[j][i-1][0]+(x[i]-x[j])*(sum[n]-(sum[i-1]-sum[j-1]), dp[j][i-1][1][1]+(x[i]-x[i-1]))*(sum[n]-(sum[i-1]-sum[j-1])))))))))))
sum는 전구 출력의 접두사와 각 구간을 나타낸다. [j,i]는 [j+1,i]와 [j,i-1]만 출시되기 때문에 상태 방정식은 위와 같다.
코드는 다음과 같습니다.
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1000;
const int inf=99999999;
int n,s;
int dp[maxn][maxn][2]={},x[maxn]={},w[maxn]={},sum[maxn]={};
inline int cime(int x,int y,int x1,int y1){
return abs(dp[x][y][2]-dp[x1][y1][1]);
}
int main()
{
scanf("%d%d",&n,&s);
memset(dp,999,sizeof(dp));
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++){
scanf("%d%d",&x[i],&w[i]);
sum[i]=sum[i-1]+w[i];
}
dp[s][s][0]=dp[s][s][1]=0;
for(int i=s;i<=n;i++)
for(int j=i-1;j>=1;j--){
dp[j][i][0]=min(dp[j+1][i][0]+(x[j+1]-x[j])*(sum[n]-(sum[i]-sum[j])),dp[j+1][i][1]+(x[i]-x[j])*(sum[n]-(sum[i]-sum[j])));
dp[j][i][1]=min(dp[j][i-1][0]+(x[i]-x[j])*(sum[n]-(sum[i-1]-sum[j-1])),dp[j][i-1][1]+(x[i]-x[i-1])*(sum[n]-(sum[i-1]-sum[j-1])));
}
printf("%d
",min(dp[1][n][1],dp[1][n][0]));
return 0;
}