不死的LYM NOIP模擬 二分+狀壓DP
阿新 • • 發佈:2017-10-27
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