用户登录
用户注册

分享至

[SGU 183] Painting the balls

  • 作者: 芙玉宝给你玉一样的肌肤
  • 来源: 51数据库
  • 2021-07-30

一、题目

来源不详,好像是个外国网站。

p e t e r peter peter n n n 个白球排成一列,他想把一些白球刷为黑色,且任意连续 m m m 个球中至少要有 2 2 2 个黑球, p e t e r peter peter 知道他需要 C i C_i Ci? 的燃料刷第 i i i个球,你的任务是找出 p e t e r peter peter 所需的最少的燃料达到目标。

2 ≤ n ≤ 1 0 4 , 2 ≤ m ≤ 100 , m ≤ n 2\leq n\leq10^4,2\leq m\leq 100,m\leq n 2n104,2m100,mn

二、解法

数据范围已经给出了很明显的提示了,设 d p [ i ] [ j ] dp[i][j] dp[i][j]为最后两个球染了 i i i i ? j i-j i?j [ 1 , i ] [1,i] [1,i]全部合法的方案数,转移考虑让 i ? 1 i-1 i?1这个位置结尾的 m m m段合法,那么:
d p [ i ] [ j ] = min ? { d p [ i ? j ] [ k ] + a [ i ] } ? k ∈ [ 1 , m ? j ] dp[i][j]=\min\{dp[i-j][k]+a[i]\}\space k\in[1,m-j] dp[i][j]=min{dp[i?j][k]+a[i]}?k[1,m?j]不难发现可以用前缀和优化。初始化我们要处理 1 ≤ i , j ≤ m 1\leq i,j\leq m 1i,jm的情况,如果状态 d p [ i ] [ j ] dp[i][j] dp[i][j]满足 m ? ( i ? j ) < n m-(i-j)<n m?(i?j)<n就可以计入答案,时间复杂度 O ( n m ) O(nm) O(nm)

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 10005;
int read()
{
    int num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
    return num*flag;
}
int n,m,ans=1e9,a[M],dp[M][105],g[M][105];
signed main()
{
	n=read();m=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	memset(g,0x3f,sizeof g);
	memset(dp,0x3f,sizeof dp);
	for(int i=1;i<=m;i++)
		for(int j=1;j<i;j++)
		{
			dp[i][j]=a[i]+a[i-j];
			g[i][j]=min(g[i][j-1],dp[i][j]);
			if(n-(i-j)<m) ans=min(ans,dp[i][j]);
		}
	for(int i=m+1;i<=n;i++)
		for(int j=1;j<m;j++)
			/*
			for(int k=1;k<=m-j;k++)
			{
				dp[i][j]=min(dp[i][j],dp[i-j][k]+a[i]);
				if(n-(i-j)<m) ans=min(ans,dp[i][j]); 
			}*/
		{
			dp[i][j]=g[i-j][m-j]+a[i];
			g[i][j]=min(g[i][j-1],dp[i][j]);
			if(n-(i-j)<m) ans=min(ans,dp[i][j]);
		}
	printf("%d\n",ans);
}
/*
i-j
dp[i][j]=dp[i-j][ [1,m-j] ] + c[i]
*/ 
软件
前端设计
程序设计
Java相关