JZYZOJ1445 [noip2014day1-T3]飞扬的小鸟 动态规划 完全背包

http://172.20.6.3/Problem_Show.asp?id=1445

很容易看出来动态规划的本质,但是之前写的时候被卡了一下(不止一下),还是写一下题解。

直接暴力O(n*m^2)大概是70分,比较划算。

100分需要对上升下降方式找规律然后优化到O(nm);

可以看出,70分算法有很多时间浪费在没必要的上升计算上,为了减少上升计算,我们可以在预处理后把上升计算变为只有一次。

把下降的放在最后处理。

观察可以发现f[i][x]的赋值只可能来自于下面升上来的,其实本质就是一个有一点特殊的完全背包,然后背包处理就可以了。(不一定要像我那样写的,我觉得其实有更好看更容易懂的写法)

最后再处理一个下降的方案比较后赋值。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<iostream>
 6 using namespace std;
 7 const int maxn=10010;
 8 int n,m,k;
 9 int a[maxn][2]={};
10 int f[maxn][1010]={},g[1010]={};
11 int d[maxn]={};
12 struct nod{
13     int p,l,h;
14 }e[maxn];
15 bool mmp(nod aa,nod bb){
16     return aa.p<bb.p;
17 }
18 int main(){
19     //freopen("wtf.in","r",stdin);
20     scanf("%d%d%d",&n,&m,&k);
21     for(int i=1;i<=n;i++){
22         scanf("%d%d",&a[i][0],&a[i][1]);
23     }
24     for(int i=1;i<=k;i++){
25         scanf("%d%d%d",&e[i].p,&e[i].l,&e[i].h);
26     }sort(e+1,e+1+k,mmp);
27     for(int i=1;i<=k;i++){
28         d[e[i].p]=i;
29     }
30     memset(f,63,sizeof(f));
31     int ans=f[1][1],cnt=f[1][1];
32     for(int i=1;i<=m;i++)f[0][i]=0;
33     int w=0;
34     for(int i=0;i<n;i++){
35         int mi=1,ma=m;
36         if(d[i]){
37             mi=e[d[i]].l+1,ma=e[d[i]].h-1;
38         }
39         int ff=0;
40         memset(g,63,sizeof(g));
41         for(int j=mi;j<=ma;j++){
42             g[j]=f[i][j];
43             if(f[i][j]!=cnt)ff=1;
44         }
45         for(int j=1;j<=m;j++){
46             int x=min(m,a[i+1][0]+j);
47             g[x]=min(g[x],g[j]+1);
48         }
49         for(int j=1;j<=m;j++){
50             int x=min(m,a[i+1][0]+j);
51             f[i+1][x]=min(f[i+1][x],g[j]+1);
52         }
53         for(int j=mi;j<=ma;j++){
54             if(j-a[i+1][1]>0) f[i+1][j-a[i+1][1]]=min(f[i+1][j-a[i+1][1]],f[i][j]); 
55         }
56         if(!ff){
57             printf("0\n%d\n",w);
58             return 0;
59         }
60         if(d[i])w++;
61     }
62     for(int i=1;i<=m;i++){
63         ans=min(ans,f[n][i]);
64     }
65     printf("1\n%d\n",ans);
66     return 0;
67 }
View Code

 

posted @ 2017-11-07 11:33  鲸头鹳  阅读(179)  评论(0编辑  收藏  举报