NOIP模擬 偷書
阿新 • • 發佈:2018-10-02
col name read nbsp 希望 out set mat code
【題目描述】
在L的書架上,有 N本精彩絕倫的書籍,每本書價值不菲。
M 是一個書籍愛好者,他對 L 的書籍早就垂涎三尺。最後他忍受不了誘惑,覺得去偷 L 的書,為了迅速完成這件事,同時他不希望 L 很快發現書籍少了,他決定偷書時,對於任意連續的 k 本書,他最多選 B 本,最少選 A 本。現在他想知道怎麽選出來的書本最後使得偷的書籍的價值和,與剩下的書籍價值和,差值最大。
【輸入格式】
第一行四個整數 n,k,a,b
一行 N 個整數表示每本書的價值
【輸出格式】
一個整數表示答案
【樣例輸入】
2 1 0 1
2 -2
【樣例輸出】
4
【備註】
對於 20%:n<=10
對於另外 20%:a=0,b=k
對於 100%:n<=1000,0<=a<=b<=k<=10,所有書籍的價值的絕對值<=10^9
【題目分析】
一看到k<=10,這麽小的數據簡直就是宣告這是一道狀壓DP的題,那麽就定義一個數組dp[i][j],其中i表示前i個,狀態為j(包含第i個)的最大價值,易得對於每個合法dp[i][j],均可從dp[i-1][j>>1]和dp[i-1][(j>>1)|(1<<k)]轉移而來,所以先預處理出所有合法情況(即1的個數大於等於a而小於等於b),最後掃一遍dp[n][k]即可。
1 #include<iostream> 2#include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<queue> 7 #include<cmath> 8 using namespace std; 9 typedef long long LL; 10 const LL MAXN=1<<11; 11 const LL INF=0x3f3f3f3f; 12 13 LL dp[1001][MAXN]; 14 LL n,k,a,b;15 LL val[1001]; 16 bool che[MAXN]; 17 18 LL Read() 19 { 20 LL i=0,f=1; 21 char c; 22 for(c=getchar();(c>‘9‘||c<‘0‘)&&c!=‘-‘;c=getchar()); 23 if(c==‘-‘) 24 f=-1,c=getchar(); 25 for(;c>=‘0‘&&c<=‘9‘;c=getchar()) 26 i=(i<<1)+(i<<3)+c-‘0‘; 27 return i*f; 28 } 29 30 void pre() 31 { 32 for(LL i=0;i<=MAXN;++i) 33 { 34 LL t=i; 35 LL cnt=0; 36 while(t) 37 { 38 if(t&1) 39 cnt++; 40 t>>=1; 41 } 42 if(cnt>=a&&cnt<=b) 43 che[i]=true; 44 } 45 } 46 47 int main() 48 { 49 memset(dp,INF,sizeof(dp)); 50 n=Read(),k=Read(),a=Read(),b=Read(); 51 LL ans=-dp[0][0],inf=dp[0][0]; 52 pre(); 53 LL tot=0; 54 for(LL i=1;i<=n;++i) 55 val[i]=Read(),tot+=val[i]; 56 for(LL j=0;j<(1<<k);++j) 57 dp[0][j]=0; 58 LL cs=1<<k; 59 for(LL i=1;i<=n;++i) 60 { 61 for(LL j=0;j<cs;++j) 62 { 63 if(che[j]) 64 { 65 if(dp[i-1][j>>1]!=inf&&dp[i-1][(j>>1)|(1<<(k-1))]!=inf) 66 { 67 if(j&1) 68 dp[i][j]=max(dp[i-1][j>>1],dp[i-1][(j>>1)|(1<<(k-1))])+val[i]; 69 else 70 dp[i][j]=max(dp[i-1][j>>1],dp[i-1][(j>>1)|(1<<(k-1))]); 71 } 72 else 73 { 74 dp[i][j]=min(dp[i-1][j>>1],dp[i-1][(j>>1)|(1<<(k-1))]); 75 if(dp[i][j]==inf) 76 continue; 77 if(j&1) 78 dp[i][j]+=val[i]; 79 } 80 } 81 } 82 } 83 for(LL i=0;i<cs;++i) 84 { 85 if(dp[n][i]==inf) 86 continue; 87 ans=max(ans,dp[n][i]); 88 } 89 cout<<ans*2-tot; 90 return 0; 91 }
NOIP模擬 偷書