1. 程式人生 > >不死的LYM NOIP模擬 二分+狀壓DP

不死的LYM NOIP模擬 二分+狀壓DP

gis using getchar() == cstring int algo true check

一共也就7種課,第7種可以貪心地選擇一定睡覺以換取答案的最小值。

那麽我們就只剩下六種課需要討論,狀態壓縮一下【當前的課之前睡過哪些課】即可。

本題要在二分的check內寫DP,用二分出來的疲勞極限作為限制條件。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
using namespace std;
template<class T> inline void read(T &_a){
    bool f=0
;int _ch=getchar();_a=0; while(_ch<0 || _ch>9){if(_ch==-)f=1;_ch=getchar();} while(_ch>=0 && _ch<=9){_a=(_a<<1)+(_a<<3)+_ch-0;_ch=getchar();} if(f)_a=-_a; } const int maxn=5001; long long n,c[maxn],js[maxn],zj[maxn],l,mid,r,init,dp[maxn][(1<<6
)+5]; inline bool check() { memset(dp,0x7f,sizeof(dp)); dp[0][0]=init; for (register int i=1;i<=n;++i) { if(c[i]==7) { for (register int v=0;v<64;++v) if (dp[i-1][v]<=mid) dp[i][v]=dp[i-1][v]-js[i]; continue; }
int symbol=(1<<(c[i]-1)); for (register int v=0;v<64;++v) { if(v&symbol) { if(dp[i-1][v^symbol]<=mid) dp[i][v]=dp[i-1][v^symbol]-js[i]; } else { if(dp[i-1][v]<=mid) dp[i][v]=min(dp[i][v],dp[i-1][v]+zj[i]); if(dp[i-1][v^symbol]<=mid) dp[i][v]=min(dp[i][v],dp[i-1][v^symbol]+zj[i]); } } } for (register int v=0;v<64;++v) if(dp[n][v]<=mid) return true; return false; } int main() { freopen("survive.in","r",stdin); freopen("survive.out","w",stdout); read(n); for (register int i=1;i<=n;++i) read(c[i]); for (register int i=1;i<=n;++i) read(js[i]); for (register int i=1;i<=n;++i) read(zj[i]),r+=zj[i]; read(init); l=init; r+=l; long long ans; while(l<=r) { mid=(l+r)>>1; if(check()) ans=mid,r=mid-1; else l=mid+1; } printf("%lld",ans); fclose(stdin); fclose(stdout); return 0; }

不死的LYM NOIP模擬 二分+狀壓DP