• Luogu P1020 关路灯


    题目传送门

    (DP)太菜了……只会抄题解……

    抄了题解的我再来向你们瞎( t{bibi},) 233~


    状态

    一道区间(DP),我们用dp[i][j]表示将第(i)盏路灯到第(j)路灯之间的路灯全部关上的最小能耗,但这样我们很难转移,根本无从下手——不知道老张的位置。

    既然我们缺少位置信息,那再加上一维不就好了么。于是我们可以用dp[i][j][0/1]表示将第(i)盏路灯到第(j)路灯之间的路灯全部关上,老张此时在第(i)盏路灯下((0))或第(j)盏路灯下((1))的最小能耗

    那么初始状态很明显就是dp[c][c][1]=dp[c][c][0]=0;

    转移

    因为我们要快速的求出总区间剔除出一段区间的和,所以可以用前缀和来维护

    十分冗长的( m{code})

    dp[i][j][0]=min(dp[i+1][j][0]+(x[i+1]-x[i])*(sum[n]-sum[j]+sum[i]),dp[i+1][j][1]+(x[j]-x[i])*(sum[n]-sum[j]+sum[i]));
    dp[i][j][1]=min(dp[i][j-1][0]+(x[j]-x[i])*(sum[n]-sum[j-1]+sum[i-1]),dp[i][j-1][1]+(x[j]-x[j-1])*(sum[n]-sum[j-1]+sum[i-1]));
    

    (mathcal{code})

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read(){
    	int k=0; char c=getchar();
    	for(;c<'0'||c>'9';) c=getchar();
    	for(;c>='0'&&c<='9';c=getchar())
    	  k=k*10+c-48;
    	return k;
    }
    int dp[51][51][2],sum[51],x[51];
    int main(){
    	int n=read(),c=read(); memset(dp,2,sizeof(dp));
    	for(int i=1;i<=n;i++) x[i]=read(),sum[i]=sum[i-1]+read();
    	dp[c][c][1]=dp[c][c][0]=0;
    	for(int j=c;j<=n;j++)
    	  for(int i=j-1;i;i--){
    	  	dp[i][j][0]=min(dp[i+1][j][0]+(x[i+1]-x[i])*(sum[n]-sum[j]+sum[i]),dp[i+1][j][1]+(x[j]-x[i])*(sum[n]-sum[j]+sum[i]));
    	  	dp[i][j][1]=min(dp[i][j-1][0]+(x[j]-x[i])*(sum[n]-sum[j-1]+sum[i-1]),dp[i][j-1][1]+(x[j]-x[j-1])*(sum[n]-sum[j-1]+sum[i-1]));
    	  }
    	cout<<min(dp[1][n][0],dp[1][n][1]);
    	return 0;
    }
    
  • 相关阅读:
    (转载)MySQL日期时间函数大全
    Tcl commands
    Toplevel
    tk 8.4 commands
    iwidgets
    Options for Buttontype widgets
    Text Widget Options
    tk options
    itk_option
    Widget Options
  • 原文地址:https://www.cnblogs.com/morslin/p/11854818.html
Copyright © 2020-2023  润新知