【数学,DP】AcWing 232. 守卫者的挑战

这题看起来不难然而一堆细节。。

分析

首先不难看出这是一个类似于背包的 dp 问题。

考虑状态的设计:f(i,j,k) 表示当前考虑到第 i 个挑战,当前背包剩余容量j,前 i 个挑战中已经成功了 k 个。

那么我们可以进一步写出转移方程:

  • i 个挑战失败时:f(i1,j,k)f(i,j,k)
  • i 个挑战成功时:f(i1,j,k)f(i,j+wi,k+1)

接下来就是细节问题了:

约定 V 为地图残片的数量。

  • 首先,注意到 wi 会非常大,直接开数组自然不行,事实上当背包容量 V 的时候能够保证装下所有的地图残片,因此我们可以对状态表示进行调整:对于 f(i,V,k) 表示当前背包剩余容量 Vi,k 定义不变。
  • 其次,因为我们是对挑战直接进行 1n 的扫描,有可能在过程中出现背包容量为负的情况,但是我们不能直接舍弃这类状态,因为有可能在未来这样的状态可以转移到背包容量为正的情况,那么我们需要想办法将这类状态也保存,具体做法是:将 j 整体加上一个 V 的偏移量(类似于将数轴平移)。
// Problem: 守卫者的挑战
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/234/
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;

#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()

inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

const int N=220;

int n, L, K, V;
double p[N];
int w[N];

int main(){
	cin>>n>>L>>K;
	rep(i,1,n) cin>>p[i], p[i]/=100;
	rep(i,1,n){
		read(w[i]);
		if(w[i]==-1) V++;
	}
	K=min(V, K);
	
	double f[n+1][V<<1|1][n+1];
	memset(f, 0, sizeof f);
	f[0][V+K][0]=1;
	
	rep(i,1,n){
		rep(j,0,V<<1) rep(k,0,n){
			f[i][j][k]+=(1.0-p[i])*f[i-1][j][k];
			if(j+w[i]>=0 && k<n) f[i][min(j+w[i], V<<1)][k+1]+=p[i]*f[i-1][j][k];
		}
	}
	
	double res=0;
	rep(i,V,V<<1) rep(j,L,n) res+=f[n][i][j]; 
	printf("%.6lf\n", res);
	
	return 0;
}
posted @   HinanawiTenshi  阅读(55)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
历史上的今天:
2021-02-15 【DP】区间DP入门
点击右上角即可分享
微信分享提示