zoukankan      html  css  js  c++  java
  • NOIP1999提高组 题解报告

    T1 导弹拦截

    题目大意:依次有(n)(n le 10^5))枚导弹,一套导弹拦截系统只能拦截一系列高度递减的导弹(一套系统拦截的弹道不一定相邻)。求一套系统最多能拦截多少导弹,以及最少需要几套系统。

    很显然,一套系统最多拦截导弹数即为导弹高度的最长不上升子序列,而需要系统数即为最长下降子序列。

    直接(O(nlogn))解决即可。

    (Code:)

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int N=1e5+5;
    int n,a[N],b[N],k1,k2,c[N];
    int main()
    {
        while(~scanf("%d",&a[++n]));--n;
        b[++k1]=a[1],c[++k2]=a[1];
        for(int i=2;i<=n;++i)
        {
            if(a[i]<=b[k1]) b[++k1]=a[i];
            else
            {
                int pos=upper_bound(b+1,b+k1+1,a[i],greater<int>())-b;
                b[pos]=a[i];
            }
            if(a[i]>c[k2]) c[++k2]=a[i];
            else
            {
                int pos=lower_bound(c+1,c+k2+1,a[i])-c;
                c[pos]=a[i];
            }
        }
        printf("%d
    %d",k1,k2);
        return 0;
    }
    
    

    T2 回文数

    题目大意:给你一个(n)进制数(m),可进行在(n)进制下的如下操作:(m)加上自身的倒序数(如(56)(65))。如此反复操作,求多少次操作后可得到一个回文数。

    简单的模拟,要注意特判(n > 10)的时候。

    (Code:)

    #include<iostream>
    #include<cstring>
    #include<string>
    using namespace std;
    int x,n,sum,a[1001];
    string s;
    inline bool hw(int n)
    {
    	for(int i=1;i<=n/2;i++)
    		if(a[i]!=a[n-i+1]) return false;
    	return true;
    }
    inline int jia(int n)
    {
    	int c[1001]={0};
    	for(int i=1;i<=n;i++)
    	{
    		c[i]+=a[i]+a[n-i+1];
    		c[i+1]+=c[i]/x;
    		c[i]%=x;
    	}
    	if(c[n+1]) n++;
    	for(int i=n;i>=1;i--) a[i]=c[i];
    	return n;
    }
    int main()
    {
    	cin>>x>>s;n=s.size();
    	for(int i=1;i<=n;++i)
    	{
    		if(s[i-1]<65) a[i]=s[i-1]-'0';
    		else a[i]=s[i-1]-55;//特判字母
    	}
    	while(sum<=30)
    	{
    		if(hw(n))
    		{
    			printf("STEP=%d",sum);
    			return 0;
    		}
    		++sum,n=jia(n);
    	}
    	puts("Impossible!");
    }
    
    

    T3 旅行家的预算

    题目大意:在长为(D_1)一条路上,有(n)个加油站,每个加油站有一个油价(p_i)和离起点的距离(d_i)。现在给出油箱容量(C)和每升汽油能行驶的距离(D_2),求是否能到终点;如果能,输出最小花费。

    仍然是模拟,还加了点贪心。

    • 在一个加油站所需要加的油,就是能够支持它到达下一个油价比它低的加油站的量

    • 如果在这个加油站即使加满油,都不能到达一个比它油价低的加油站,就把油箱加满,前往能够到达的加油站中油价最低的那个(贪心地想,这种决策肯定是能省钱的)

    (Code:)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define db double
    int n;
    db D1,v,D2,P[233],D[233];
    db solve()
    {
        db s=v*D2;//车能开的距离
        db sum=(1.0*D[1]/D2)*P[0];//总费用
        db sumD=D[1];
        if(D[1]>s) return -1;
        db now=P[0];//设为当前使用的油价
        for(int i=1;i<=n;++i)
            if(P[i]-P[i-1]>s) return -1;
        int i=1;
        while(i<=n)
        {
            if(P[i]>=now)
            {
                sumD+=D[i+1]-D[i];
                if(sumD>s)
                {
                    sum+=(1.0*(s-(sumD-(D[i+1]-D[i])))/D2)*now;
                    now=P[i],sumD=sumD-s;
                    sum+=(1.0*sumD/D2)*now;
                }
                else sum+=(1.0*(D[i+1]-D[i])/D2)*now;
                ++i;
            }
            else now=P[i],sumD=0;
        }
        return sum;
    }
    int main()
    {
        scanf("%lf%lf%lf%lf%d",&D1,&v,&D2,&P[0],&n);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&D[i],&P[i]);
        D[n+1]=D1;
        db sum=solve();
        if(sum<0) puts("No Solution");
        else printf("%.2lf
    ",sum);
        return 0;
    }
    
    

    T4 邮票面值设计

    题目大意:给定一个信封,最多只允许粘贴(n)张邮票,有(k)((n + k le 15))种邮票要用(所有的邮票数量都足够),如何设计邮票的面值,能得到最大值(MAX),使在(1)(MAX)之间的每一个邮资值都能得到。

    很显然是个爆搜题,不过爆搜的范围怎么确定呢?
    我们发现,如果令$p = (选完上一个数可拼成的面值,则当前数的范围为)[上一个数 + 1 , p + 1]((这个道理仔细想一下就明白了) 确定最大面值的问题,就可以用完全背包来解决啦! 定义)dp[i](为拼成)i(最少需要的邮票数,则状态转移方程为:)dp[i] = min(dp[i],dp[i - a[j]] + 1)( )Code:$

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int inf=0x3f3f3f3f;
    #define rg register
    vector<int>ans,temp;
    int n,k,dp[2333],Ans;
    inline int f()
    {
        memset(dp,inf,sizeof dp),dp[0]=0;
        for(rg int i=1;;++i)
        {
            for(rg int j=0;j<(int)temp.size() && temp[j]<=i;++j)
                dp[i]=min(dp[i],dp[i-temp[j]]+1);
            if(dp[i]>n)
            {
                if(i>Ans+1) Ans=i-1,ans=temp;
                return i-1;
            }
        }
    }
    inline void dfs(int d)
    {
        int p=f();
        for(rg int i=temp[(int)temp.size()-1]+1;i<=p+1;++i)
        {
            temp.push_back(i),f();
            if(d<k) dfs(d+1);
            temp.pop_back();
        }
    }
    int main()
    {
        scanf("%d%d",&n,&k);temp.push_back(1);
        dfs(2);
        for(rg int i=0;i<ans.size();++i) printf("%d ",ans[i]);
        printf("
    MAX=%d",Ans);
        return 0;
    }
    
    
  • 相关阅读:
    EntityFramework优缺点
    领导者与管理者的区别
    七个对我最好的职业建议(精简版)
    The best career advice I’ve received
    Difference between Stored Procedure and Function in SQL Server
    2015年上半年一次通过 信息系统项目管理师
    Difference between WCF and Web API and WCF REST and Web Service
    What’s the difference between data mining and data warehousing?
    What is the difference between a Clustered and Non Clustered Index?
    用new创建函数的过程发生了什么
  • 原文地址:https://www.cnblogs.com/p-z-y/p/11720355.html
Copyright © 2011-2022 走看看