题目:https://www.luogu.org/problemnew/show/P1220
先要发现任一时刻已关的灯属于连续的区间(不会路过而不关灯)。
精髓在于分类左端点和右端点。
但没想清楚为何memset不行。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,p,a[55]; long long d[55][55][2],all,c[55]; const int INF=0x7fffffff; long long sum(int a,int b) { long long s=0; for(int i=a;i<=b;i++) s+=c[i]; return s; } long long mn(long long a,long long b) { if(a<b)return a;return b; } int main() { scanf("%d%d",&n,&p); for(int i=1;i<=n;i++) { scanf("%d%lld",&a[i],&c[i]); all+=c[i]; } // memset(d,INF,sizeof d); 不行 for(int i=1;i<=n;i++)d[i][i][0]=INF,d[i][i][1]=INF; d[p][p][0]=0;d[p][p][1]=0; for(int L=2;L<=n;L++) for(int i=1;i<=n-L+1;i++) { int j=i+L-1; d[i][j][0]=mn(d[i+1][j][0]+(a[i+1]-a[i])*(all-sum(i+1,j)),d[i+1][j][1]+(a[j]-a[i])*(all-sum(i+1,j))); d[i][j][1]=mn(d[i][j-1][1]+(a[j]-a[j-1])*(all-sum(i,j-1)),d[i][j-1][0]+(a[j]-a[i])*(all-sum(i,j-1))); } printf("%lld",mn(d[1][n][0],d[1][n][1])); return 0; }