没有这么麻烦。dp[i][j][2]表示关掉i-j左端点和右端点的最小值,初始化起点为0,其他为inf。就是一道裸题。代码:
```c
#include<bits/stdc++.h>
using namespace std;
int dp[60][60][2];//dp[i][j][0/1]顾名思义,关掉i-j内所有的灯在左端点或者右端点的最小花费。
int a[60];//预处理前缀功率之和。
int w[60];
int n,st,pos[60];
int main()
{
scanf("%d%d",&n,&st);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&pos[i],&w[i]);
}
for(int i=1;i<=n;i++)
{
a[i]=a[i-1]+w[i];
}
memset(dp,0x7f7f7f,sizeof(dp));
dp[st][st][0]=dp[st][st][1]=0;
for(int i=st;i>=1;i--)
{
for(int j=st;j<=n;j++) //状态转移不在赘述。
{
dp[i][j][0]=min(dp[i][j][0],min(dp[i+1][j][0]+(a[n]-a[j]+a[i])*(pos[i+1]-pos[i]),dp[i+1][j][1]+(a[n]-a[j]+a[i])*(pos[j]-pos[i])));
dp[i][j][1]=min(dp[i][j][1],min(dp[i][j-1][1]+(a[n]-a[j-1]+a[i-1])*(pos[j]-pos[j-1]),dp[i][j-1][0]+(a[n]-a[j-1]+a[i-1])*(pos[j]-pos[i])));
}
}
printf("%d",min(dp[1][n][0],dp[1][n][1]));
return 0;
}
```
by 丶Cyanide @ 2018-07-19 16:42:00