题目链接:Timetable
题意:Ivan是一个学生,在一个Berland周内要上n天课,每天最多会有m节,他能逃课的最大数量是k。求他在学校的时间最小是多少?
题解:先把每天逃课x节在学校呆的最小时间预处理出来,这样就变成了在n天里面,每个组有不同的情况,找出逃课t节的能在学校呆最小时间的情况。就是一个分组背包问题了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAX_N = 5e2+9; 4 const int INF = 1e9+9; 5 int N,M,T,S; 6 int num[MAX_N]; 7 int pos[MAX_N][MAX_N]; 8 char vec[MAX_N][MAX_N]; 9 int v[MAX_N][MAX_N]; 10 int dp[MAX_N]; 11 int main(){ 12 while(cin>>N>>M>>T){ 13 memset(num,0,sizeof(num)); 14 for(int i=0;i<MAX_N;i++) memset(pos[i],0,sizeof(pos[i])); 15 for(int i=0;i<N;i++){ 16 scanf("%s",vec[i]); 17 for(int j=0;j<M;j++){ 18 if(vec[i][j] == '1'){ 19 num[i] ++ ; 20 pos[i][num[i]] = j; 21 //cout<<i<<" "<<num[i]<<" "<<j<<endl; 22 } 23 } 24 } 25 //预处理 26 for(int i=0;i<N;i++){ 27 for(int j=0;j<=min(num[i]-1;j++){ 28 int t = INF; 29 for(int p=0;p<=j;p++){ 30 int q = j - p; 31 t = min(t,pos[i][num[i]-q] - pos[i][p+1] + 1 ); 32 } 33 v[i][j] = M-t; 34 } 35 v[i][num[i]] = M; 36 } 37 //分组背包 38 for(int i=0;i<N;i++){ 39 for(int j=T;j>=0;j--){ 40 for(int k = 0;k<=min(j,M);k++){ 41 dp[j] = max(dp[j] , dp[j-k]+v[i][k]); 42 } 43 } 44 } 45 cout<<N*M-dp[T]<<endl; 46 47 } 48 return 0; 49 } 50 /* 51 9 1 52 0 1 1 1 1 1 6 7 8 53 */