zoukankan      html  css  js  c++  java
  • 20200929 day23 刷题记录

    1 P1941 飞扬的小鸟

    题目描述

    Flappy Bird 是一款风靡一时的休闲手机游戏。玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙。如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败。 为了简化问题,我们对游戏规则进行了简化和改编: 游戏界面是一个长为 (n),高为 (m) 的二维平面,其中有 (k) 个管道(忽略管道的宽度)。 小鸟始终在游戏界面内移动。小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成。 小鸟每个单位时间沿横坐标方向右移的距离为 (1),竖直移动的距离由玩家控制。如果点击屏幕,小鸟就会上升一定高度 (x),每个单位时间可以点击多次,效果叠加;如果不点击屏幕,小鸟就会下降一定高度 (y)。小鸟位于横坐标方向不同位置时,上升的高度 (x) 和下降的高度 (y) 可能互不相同。 小鸟高度等于 (0) 或者小鸟碰到管道时,游戏失败。小鸟高度为 (m) 时,无法再上升。 现在,请你判断是否可以完成游戏。如果可以,输出最少点击屏幕数;否则,输出小鸟最多可以通过多少个管道缝隙。

    输入输出格式

    输入格式

    (1) 行有 (3) 个整数 (n, m, k),分别表示游戏界面的长度,高度和水管的数量,每两个整数之间用一个空格隔开; 接下来的 (n) 行,每行 (2) 个用一个空格隔开的整数 (x)(y),依次表示在横坐标位置 (0 sim n-1) 上玩家点击屏幕后,小鸟在下一位置上升的高度 (x),以及在这个位置上玩家不点击屏幕时,小鸟在下一位置下降的高度 (y)。 接下来 (k) 行,每行 (3) 个整数 (p,l,h),每两个整数之间用一个空格隔开。每行表示一个管道,其中 (p) 表示管道的横坐标,(l) 表示此管道缝隙的下边沿高度,(h) 表示管道缝隙上边沿的高度(输入数据保证 (p) 各不相同,但不保证按照大小顺序给出)。

    输出格式

    共两行。 第一行,包含一个整数,如果可以成功完成游戏,则输出 (1),否则输出 (0)。 第二行,包含一个整数,如果第一行为 (1),则输出成功完成游戏需要最少点击屏幕数,否则,输出小鸟最多可以通过多少个管道缝隙。

    输入输出样例

    输入样例 #1

    10 10 6 
    3 9  
    9 9  
    1 2  
    1 3  
    1 2  
    1 1  
    2 1  
    2 1  
    1 6  
    2 2  
    1 2 7 
    5 1 5 
    6 3 5 
    7 5 8 
    8 7 9 
    9 1 3 
    

    |### 输出样例 #1

    1
    6
    

    输入样例 #2

    10 10 4 
    1 2  
    3 1  
    2 2  
    1 8  
    1 8  
    3 2  
    2 1  
    2 1  
    2 2  
    1 2  
    1 0 2 
    6 7 9 
    9 1 4 
    3 8 10  
    

    输出样例 #2

    0
    3
    

    说明

    【输入输出样例说明】
    如下图所示,蓝色直线表示小鸟的飞行轨迹,红色直线表示管道。

    【数据范围】
    对于 (30\%) 的数据:(5 leq n leq 10, 5 leq m leq 10, k=0),保证存在一组最优解使得同一单位时间最多点击屏幕 (3) 次;
    对于 (50\%) 的数据:(5 leq n leq 20, 5 leq m leq 10),保证存在一组最优解使得同一单位时间最多点击屏幕 (3) 次;
    对于 (70\%) 的数据:(5 leq n leq 1000, 5 leq m leq 100)
    对于 (100\%) 的数据:(5 leq n leq 10000)(5 leq m leq 1000)(0 leq k < n)(0 < x,y < m)(0 < p < n)(0 leq l < h leq m)(l + 1 < h)

    题解

    向上飞是完全背包(可以多次点)
    向下跳是01背包(只能向下跳1格)
    碰到最上端不能再飞
    最后统计最大值情况即可
    (虽然说还是好难)

    注意

    (m,n)不要读反了!!!!!!!!

    代码

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    int n,m,k;//长n宽m
    int x[10005],y[10005];
    int low[10010],high[10010];
    int f[10010][2010];
    bool e[10010];//e[i]位置是否有管道
    int ans;
    int main(){
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=n;++i){
    		scanf("%d%d",&x[i],&y[i]);
    	}
    	for(int i=1;i<=n;++i){
    		low[i]=1;high[i]=m;
    	}
    	int a,b,c;
    	for(int i=1;i<=k;++i){
    		scanf("%d%d%d",&a,&b,&c);
    		e[a]=1;
    		low[a]=b+1;
    		high[a]=c-1;//i坐标可通过的位置是low[i]~high[i]
    	}
    	//上升 完全背包 下降 01背包
    	memset(f,0x3f,sizeof(f));
    	for(int i=1;i<=m;++i) f[0][i]=0;
    	for(int i=1;i<=n;++i){
    		for(int j=x[i]+1;j<=m+x[i];++j)
    			f[i][j]=min(f[i-1][j-x[i]]+1,f[i][j-x[i]]+1);
    		for(int j=m+1;j<=m+x[i];++j)
    			f[i][m]=min(f[i][m],f[i][j]);
    		for(int j=1;j<=m-y[i];++j)
    			f[i][j]=min(f[i][j],f[i-1][j+y[i]]);
    		for(int j=1;j<low[i];++j)
    			f[i][j]=f[0][0];//不能通过INF
    		for(int j=high[i]+1;j<=m;++j)
    			f[i][j]=f[0][0];
    	}
        int ans=f[0][0];
        for(int j=1;j<=m;++j) {
            ans=min(ans,f[n][j]);
        }
        if(ans<f[0][0]) printf("1
    %d
    ",ans);
        else{
            int i,j;
            for(i=n;i>=1;i--) {
                for(j=1;j<=m;++j) {
                    if(f[i][j]<f[0][0]) break;
                }
                if(j<=m) break;
            }
            ans=0;
            for(int j=1;j<=i;++j) {
                if(e[j]) ans++;
            }
            printf("0
    %d
    ",ans);
        }
        return 0;
    }
    

    2 P1144 最短路计数

    题面

    给出一个(N)个顶点(M)条边的无向无权图,顶点编号为(1-N)。问从顶点(1)开始,到其他每个点的最短路有几条。
    输入输出格式
    输入格式

    第一行包含(2)个正整数(N,M),为图的顶点数与边数。 接下来(M)行,每行(2)个正整数(x,y),表示有一条顶点(x)连向顶点(y)的边,请注意可能有自环与重边。

    输出格式

    (N)行,每行一个非负整数,第(i)行输出从顶点(1)到顶点(i)有多少条不同的最短路,由于答案有可能会很大,你只需要输出$ ans mod 100003$ 后的结果即可。如果无法到达顶点 (i)则输出(0)

    输入输出样例

    输入样例 #1

    5 7
    1 2
    1 3
    2 4
    3 4
    2 3
    4 5
    4 5
    

    输出样例 #1

    1
    1
    1
    2
    4
    

    说明

    (1)(5)的最短路有(4)条,分别为(2)(1-2-4-5)(2)(1-3-4-5)(由于(4-5)的边有(2)条)。
    对于(20\%)的数据,(N ≤ 100)
    对于(60\%)的数据,(N ≤ 1000)
    对于(100\%)的数据,(N<=1000000,M<=2000000)

    题解

    dij?SPFA?bfs?

    代码

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int maxn=1000005,maxm=4000005;
    int mod=100003;
    int n,m,cnt;
    struct node{
    	int to,next;
    }edge[maxn<<1];
    int head[maxn],ans[maxn],d[maxn];
    #include <queue>
    priority_queue<pair<int,int> > q;
    void add(int x,int y){
    	cnt++;
    	edge[cnt].to=y;
    	edge[cnt].next=head[x];
    	head[x]=cnt;
    }
    bool p[maxn];
    int main(){
    	scanf("%d%d",&n,&m);
    	int x,y;
    	for(int i=1;i<=m;i++){
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    	}
    	for(int i=1;i<=n;i++){
    		d[i]=1e9;p[i]=0;
    	}
    	d[1]=0;ans[1]=1;
    	q.push(make_pair(0,1));
    	while(q.size()){
    		x=q.top().second;
    		q.pop();
    		if(p[x]) continue;
    		p[x]=1;
    		for(int i=head[x];i;i=edge[i].next){
    			y=edge[i].to;
    			if(d[y]>d[x]+1){
    				d[y]=d[x]+1;
    				ans[y]=ans[x];
    				q.push(make_pair(-d[y],y));
    			}
    			else if(d[y]==d[x]+1){
    				ans[y]+=ans[x];
    				ans[y]%=mod;
    			}
    		}
    	}
    	for(int i=1;i<=n;i++){
    		printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
    要做就做南波万
  • 相关阅读:
    很简单的企业管理器我写程序的方式,几个自定义控件。
    当OO遇到了持久化?!
    [自定义服务器控件] 第一步:文本框。
    [面向过程——老酒换新瓶] (一)开篇:是面向过程还是面向对象?
    个人理财小助手 —— 设计思路、功能说明
    《Head First 设计模式》 终于出中文版了。
    其实添加数据也可以这样简单——表单的第一步抽象(针对数据访问层)《怪怪设计论: 抽象无处不在 》有感
    基类、接口的应用——表单控件:一次添加、修改一条记录,一次修改多条记录。(上)
    其实添加数据也可以这样简单——表单的第三步抽象(针对UI及后置代码)
    转帖:客户端表单通用验证checkForm(oForm) js版
  • 原文地址:https://www.cnblogs.com/liuziwen0224/p/20200929day23-001.html
Copyright © 2011-2022 走看看