bzoj2073: [POI2004]PRZ

思路:看到n十分于是考虑状压dp,先预处理出处于状态s的情况下过桥的时间和重量,然后枚举状态转移即可,f[i]=min(f[i],f[j]+time[i^j])(j∈i)(自称会状压dp结果连枚举非空子集都不会的我。。。。。)

顺便普及如何枚举非空子集:for (int j=i;j;j=j&(i-1));j就是i的所有非空子集。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 20
#define maxf 1<<20
 
int limit,n;
int a[maxn],b[maxn];
int t[maxf],w[maxf],dp[maxf];
 
int main(){
    scanf("%d%d",&limit,&n);
    for (int i=1;i<=n;i++)
        scanf("%d%d",&a[i],&b[i]);
    for (int i=1;i<(1<<n);i++)
        for (int j=0;j<n;j++)
            if (i&(1<<j)){
                t[i]=max(t[i],a[j+1]);
                w[i]+=b[j+1];
            }
    memset(dp,127,sizeof(dp)),dp[0]=0;
    for (int i=1;i<(1<<n);i++)
        for (int j=i;j;j=i&(j-1))
            if (w[j]<=limit) dp[i]=min(dp[i],t[j]+dp[i^j]);
    printf("%d\n",dp[(1<<n)-1]);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/DUXT/p/5990711.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值