【NOIP2014提高组】飞扬的小鸟

题目传送门:https://www.luogu.org/problem/show?pid=1941

不难看出,此题为动态规划。

我们用f[i][j]表示从第一行到达第i行第j列时点击屏幕的最少次数。

不难推出,f[i][j]=min(f[i1][j+y[i1]],f[i1][jkx[i1]]+k),其中k为整数,且j+y[i1]jkx[i1]需在合法范围内,(i,j)不能是柱子。

显然,这个转移的时间复杂度是O(nm2)的,只有70分,下面考虑进行优化。

先考虑只向上跳的情况,对于转移f[i][j]=f[i1][j2x[i1]+2,我们不妨设f[i][1..j]f[1..i][1..m]已经全部是最优解,那么在考虑f[i][j]时,只需要判断f[i1][jx[i1]f[i][jx[i1]哪个更优即可。

对于每一列,处理完向上跳的情况后,再处理向下滑行的状态。(我这里写挫了只剩下75,只能说数据实在太水)

PS:对于鸟贴顶的情况,需要特殊判断。

这样时间复杂度为O(nm)

 

复制代码
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define M 10100
 5 using namespace std;
 6 int f[M][1010]={0},b[M][1010]={0},n,m,k;
 7 int x[M]={0},y[M]={0};
 8 
 9 int get(int x,int y){
10     if(y<=0) return f[0][0];
11     if(y>m) return f[0][0];
12     return f[x][y];
13 }
14 
15 int main(){
16     scanf("%d%d%d",&n,&m,&k);
17     for(int i=0;i<n;i++) scanf("%d%d",x+i,y+i);
18     for(int i=1;i<=k;i++){
19         int p,l,h; scanf("%d%d%d",&p,&l,&h);
20         for(int ii=h;ii<=m;ii++) b[p][ii]=i;
21         for(int ii=0;ii<=l;ii++) b[p][ii]=i;
22     }
23     memset(f,1,sizeof(f)); 
24     for(int i=1;i<=m;i++) f[0][i]=0;
25     for(int i=1;i<=n;i++){
26         for(int j=1;j<=m;j++){
27             f[i][j]=min(f[i][j],get(i-1,j-x[i-1])+1);
28         }
29         for(int j=1;j<=m;j++)
30             f[i][j]=min(f[i][j],get(i,j-x[i-1])+1);
31         for(int j=m;j>=m-x[i-1];j--){
32             f[i][m]=min(f[i][m],f[i-1][j]+1);
33             f[i][m]=min(f[i][m],f[i][j]+1);
34         }
35             
36         for(int j=1;j<=m;j++)
37             f[i][j]=min(f[i][j],get(i-1,j+y[i-1]));
38         for(int j=1;j<=m;j++) if(b[i][j])
39         f[i][j]=f[0][0];
40     }
41     int minn=f[0][0];
42     for(int i=1;i<=m;i++) minn=min(minn,f[n][i]);
43     if(minn!=f[0][0]){
44         printf("1\n%d\n",minn);
45         return 0;
46     }
47     for(int i=n-1;i>=0;i--){
48         for(int j=1;j<=m;j++) if(f[i][j]!=f[0][0]){
49             int ans=0;
50             for(int ii=1;ii<=i;ii++) if(b[ii][m]) ans++;
51             printf("0\n%d\n",ans);
52             return 0;
53         }
54     }
55 }
复制代码

 

posted @   AlphaInf  阅读(345)  评论(4编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示