BZOJ1700: [Usaco2007 Jan]Problem Solving 解题

每月m<=1000块钱,有n<=300道题,要按顺序做,每月做题要花钱,花钱要第一个月预付下个月立即再付一次,给出预付和再付求最少几个月做完题,第一个月不做。

神奇的DP。。竟没想出来。。

注意到这个月做题受制于上个月做的题,f[i][j]--最后做i~j题的最少月数,f[i][j]=inf(i~j不能在一个月内做完)min(f[k][i-1]+2)(做k~i-1题后再付后不能在该月立即做i~j)min(f[k]i-1]+1)(k~i-1题后再付后可立即做i~j)

括号里的判断用前缀和即可。注意判断能不能一个月做完要考虑再付!!

感谢数据http://blog.sina.com.cn/s/blog_8d5d2f0401017kfk.html

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 //#include<iostream>
 5 using namespace std;
 6 
 7 int n,m;
 8 #define maxn 311
 9 int f[maxn][maxn],a[maxn],b[maxn],sa[maxn],sb[maxn];
10 const int inf=0x3f3f3f3f;
11 int main()
12 {
13     scanf("%d%d",&m,&n);sa[0]=sb[0]=0;
14     for (int i=1;i<=n;i++)
15     {
16         scanf("%d%d",&a[i],&b[i]);
17         sa[i]=sa[i-1]+a[i];
18         sb[i]=sb[i-1]+b[i];
19     }
20     for (int i=1;i<=n;i++) if (sa[i]<=m && sb[i]<=m) f[1][i]=3;else f[1][i]=inf;
21     for (int j=2;j<=n;j++)
22         for (int i=2;i<=j;i++)
23         {
24             f[i][j]=inf;int tmp=sa[j]-sa[i-1];
25             if (tmp<=m && sb[j]-sb[i-1]<=m) for (int k=1;k<i;k++)
26             {
27                 if (sb[i-1]-sb[k-1]+tmp>m)
28                 f[i][j]=min(f[i][j],f[k][i-1]+2);
29                 else f[i][j]=min(f[i][j],f[k][i-1]+1);
30             }
31         }
32     int ans=inf;
33     for (int i=1;i<=n;i++) ans=min(ans,f[i][n]);
34     printf("%d\n",ans);
35     return 0;
36 }
View Code

 

posted @ 2017-08-27 20:26  Blue233333  阅读(182)  评论(0编辑  收藏  举报