算法练习11&部分题&&贪心思想专题

问题 A: XP的素数

题目描述
XP最近对素数很痴迷,特别是那些特殊的素数,其中有一类素数被称为孪生素数。其定义如下:如果一个数k是素数,k+2也是素数,那么k和k+2成为一对孪生素数。请计算一个给定区间m和n(0<m<n)中孪生素数对的个数。
输入
单组输入数据
m n
(0<m<n<1000)
输出
请输出一行结果:区间[m,n]中孪生素数对的个数
在这里插入图片描述

#include<bits/stdc++.h>

#define ll long long
const int N=1005;
#include<bits/stdc++.h>
using namespace std;
int coun;
int s;
int a[N];
int prime(int n){//判断素数
    if(n==1)//注意输入的数据,如果为1则不是素数
        return 0;
     for(int j=2;j<=sqrt(n);j++){//调用平方根函数,减少时间
            if(n%j==0){
                return 0;
            }
        }
        return 1;
}
int main(){
    int m,n;
    int cou=0;
    cin>>m>>n;
    for(int i=m;i+2<=n;i++){
       if(prime(i)&&prime(i+2))
            cou++;
    }
    cout<<cou<<endl;
return 0;
}

问题 B: XP的三角形

题目描述
XP最喜欢的图形是三角形,最近他在研究直角三角形,他想到这么一个问题,如果三边长{a,b,c}均为整数的直角三角形周长为p,(a<=b<=c)当p = 120时,恰好存在三个不同的解:{a=20,b=48,c=52}, {a=24,b=45,c=51}, {a=30,b=40,c=50}。现在给定一个p求不同的解的个数。(p<=1000)
输入
单组输入数据

p

输出
输出一行结果
在这里插入图片描述

#include<bits/stdc++.h>

#define ll long long
const int N=1005;
#include<bits/stdc++.h>
using namespace std;
int coun;
int s;
int a[N];

int main(){
    int p,ct=0;
    cin>>p;
    for(int i=1;i<p;i++){
        for(int j=i;j<p;j++){
            if((i*i+j*j)==(p-i-j)*(p-i-j)){
                ct++;
            }
        }
    }
    cout<<ct<<endl;
return 0;
}

问题 C: XP的点滴

题目描述
XP一不留神感冒了,于是跑到校医院打点滴。打点滴真是无聊啊,他看到盐水一滴一滴地滴下来,突然想到一个问题:如果盐水有规律地滴下,先滴一滴,停一下;然后滴二滴,停一下;再滴三滴,停一下…,假设这瓶盐水一共有n毫升,每一滴是y毫升,每一滴需要的时间是一秒(假设最后一滴不到y毫升,需花费的时间也算一秒),停一下的时间也是一秒。请问XP多久能挂完这瓶盐水呢?
输入

单组输入数据

n y (0<n,y<=1000)

输出
输出一行结果
在这里插入图片描述

#include<bits/stdc++.h>

#define ll long long
const int N=1005;
#include<bits/stdc++.h>
using namespace std;
int coun;
int s;
int a[N];
//这里是每滴一滴就是1秒
int main(){
    int n,y,sm=0;
    int ct=0;
    cin>>n>>y;
   int  tim = ceil(n*1.0/y);//向上取整,比如ceil(1.2)=2,用来解决问题中最后一滴,剩余而不足Y毫升
   if(tim==1){//如果不足Y毫升就输出,结束程序
    cout<<tim<<endl;
    return 0;
   }else{
       int t=tim;
       int i=1;//用来代表每次滴下的滴数
       ct=1;//用来计数每次间隔停一下的时间
   while(t){
        t-=i;//减去滴数
     i+=1;
     if(t-i<=0)
        break;
        ct++;
   }

   }
   cout<<tim+ct<<endl;//输出每滴时间+间隔停止时间
return 0;
}

问题 D: 月饼

题目描述
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。

注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得 72 + 45/2 = 94.5(亿元)。
输入
每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正实数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正实数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。
在这里插入图片描述
千万别信这个题目所说的是什么整数,还有什么东西,俺试过自己按照部分背包的思想写过的代码,都没过,86%的错误,还在其他博客找过代码,都没过,在下面是AC代码,有点莫名其妙的坑,莫名其妙,俺菜的抠脚

#include<bits/stdc++.h>
using namespace std;
typedef struct {
    double kucu=0;//库存
    double shoujia=0;//售价
    double price=0;//单位库存的价钱
}Pie;
Pie pie[1005];
bool cmp(Pie a,Pie b)//排序比较函数,降序
{
    return a.price>b.price;
}
int main()
{
    int n=0;
    double xuqiu=0;
    while(scanf("%d%lf",&n,&xuqiu)!=EOF)
    {
            double money=0;
            double sum=0,maxn=0;
            for(int i=0;i<n;i++)
        {
            scanf("%lf",&pie[i].kucu);
        }
        for(int i=0;i<n;i++)
        {
            scanf("%lf",&pie[i].shoujia);
            pie[i].price=pie[i].shoujia/pie[i].kucu;
        }
        sort(pie,pie+n,cmp);


        for(int i=0;i<n;i++)
        {
            double temp=xuqiu-pie[i].kucu;//用来存储剩余的库存
            if(temp>0.0)
            {
                xuqiu=temp;
                money=money+pie[i].shoujia;

            }
            else//当不足需求时,装一部分	
            {
                money=money+xuqiu*pie[i].price;
                printf("%.2lf\n",money);
                return 0;
            }

        }
    }
    return 0;
}

问题 E: 今年暑假不AC

题目描述
“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%…”

确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
输入
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。
输出
对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef struct {
    int stime;//用来存放开始时间
    int etime;//用来存放结束时间
}Tme;
Tme tme[1005];
bool cmp(Tme& a,Tme& b)//用来排序,将结束时间升序,越早结束的能够为后面让出更多时间观看更多节目
{
    return a.etime<b.etime;
}
int main()
{
    int n;

    while(~scanf("%d",&n)&&n)
    {
        int last=1;//用来存放节目,因为求得是节目个数,没有别的约束,是从第一个开始的
           for(int i=0;i<n;i++){
            cin>>tme[i].stime>>tme[i].etime;
           }
           sort(tme,tme+n,cmp);

              int temp=tme[0].etime;//用来表示每个可以观看的当前结束时间
           for(int j=1;j<n;j++){
            if(tme[j].stime>=temp){//只要结束时间小于等于下一个节目的开始时间,就可以进行观看,而且由于结束时间排过序,结果是最优的
                temp=tme[j].etime;
            last++;
            }
           }
           cout<<last<<endl;



    }
    return 0;
}

问题 F: 最优装载

题目描述
使用贪心算法求解最优装载问题。
输入
每组输入包括两部分,
第一行包括集装箱个数n,以及船的装载量C。
接下来n行每行则输入集装箱编号以及其重量。

输出
输出包括两行,第一行为最多可装载的集装箱数量 。
第二行则为最优装载方案对应的所有集装箱编号(用空格隔开) 。
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef struct {
    int id;//用来存放每个箱子的ID,因为排序过程会打乱,需要这个进行记录
    double w;//用来存放重量
}Box;
Box boxs[1005];
int x[1005];//用来记录哪个箱子被相中
bool cmp(Box& a,Box& b)
{
    return a.w<b.w;//升序,达到装的最多的箱子
}
int main()
{
    int n;
    double all;
    while(~scanf("%d %lf",&n,&all))
    {
        int last=0;
        memset(x,0,sizeof(x));
     for(int i=1;i<=n;i++){
        cin>>boxs[i].id>>boxs[i].w;
     }
     sort(boxs+1,boxs+n+1,cmp);//因为是从1开始记录的,所以都要加一
     for(int j=1;j<=n;j++){
        double temp=all-boxs[j].w;//用来判断船的容量是否装满
        if(temp>=0.0){
                all=temp;//更新船的容量
            last++;
            x[j]=1;//记录箱子被装载
        }
     }
     cout<<last<<endl;
     for(int k=1;k<=n;k++){//用来输出被装载的箱子,1代表被装载,则输出
        if(x[k]){
            cout<<boxs[k].id<<" ";
        }
     }
     cout<<endl;



    }
    return 0;
}

问题 G: 最小生成树(Prim)

题目描述
使用Prim算法求图的最小生成树(MST)
输入
每组数据分为两个部分,第一部分为图的点数n,和边数m,
第二部分为m行,每一行输入三个数字,前两个为两个顶点的编号,第三个为边权重。
输出
最小生成树,输出时按照边的两个端点的升序输出。(先看左端点,再看右端点,端点不换位置)
在这里插入图片描述

#include<bits/stdc++.h>

using namespace std;
const int N=1005;
int INF=100000;
//运用贪心思想,在每一步求最优,得到结果是最优的
typedef struct{//用来保存符合要求的答案
    int x;
    int y;
    int v;
} Node;
typedef struct{//用来保存原始边的信息
    int x;
    int y;
    int v;
}M;
M mp[N];
bool cmp(Node& a,Node&b){//用来排序参数
    if(a.x==b.x)
        return a.y<b.y;
    return a.x<b.x;
}
Node node[N];
int main()
{
    int n,m;
    int e1,e2;
    int v;
    while(~scanf("%d %d",&n,&m)){
            int s[n+1];
        int G[n+1][n+1];
        int leng[n+1];
        int used[n+1];

        for(int ii=0;ii<n;ii++){//初始化图
            for(int jj=0;jj<n;jj++){

                    G[ii][jj]=INF;
            }
        }
        int flag=0;
        for(int k=0;k<m;k++){//存入数据,再保存边的信息
            cin>>e1>>e2>>v;
            G[e1][e2]=G[e2][e1]=v;
            mp[k].x=e1;
            mp[k].y=e2;
            mp[k].v=v;
        }
        for(int i=0;i<n;i++){//初始化第一个带你到其他点的权值
            leng[i]=G[0][i];
            s[i]=0;
            used[i]=0;
        }
        used[0]=1;
        for(int i=1;i<n;i++){
            int j=0;
            for(int k=0;k<n;k++){//选出这一点到其他点权值最少的点
                   // cout<<"leng"<<leng[j]<<" ";
                if((!used[k])&&leng[k]<leng[j]){
                      j=k;
               //       cout<<"test:"<<j<<" "<<leng[k]<<" ";
                }
            }
           // cout<<endl;
           node[flag].x=s[j];//用来保存符合题意的答案
           node[flag].y=j;
           node[flag].v=leng[j];
                flag++;
                used[j]=1;
                for(int k=1;k<n;k++){//用来更新这一点到其他点的权值
                    if((!used[k])&&G[j][k]<leng[k]){
                        leng[k]=G[j][k];
                        s[k]=j;
                  //      cout<<"test2:"<<leng[k]<<" "<<s[k]<<" ";
                    }
                }
            //    cout<<endl;


            }
           sort(node,node+flag,cmp);//按照题意用来排序
           for(int k=0;k<flag;k++){
                int temp=0;//用来判断是否与输入是否一样
                for(int i=0;i<n;i++){
                       if( node[k].x==mp[i].x&&node[k].y==mp[i].y){
                           //  printf("testppp:%d %d %d\n",node[k].x,node[k].y,node[k].v);
                           temp=1;
                           break;
                          }

                }
                if(temp){//如果存在则按照正常输出,反之,则反向输出
                    printf("%d %d %d\n",node[k].x,node[k].y,node[k].v);
                }else{
                  printf("%d %d %d\n",node[k].y,node[k].x,node[k].v);
                }


           }
    }





    return 0;
}



问题 H: XP的小视频

题目描述
XP的表哥为他推荐了一些学习计算机编程的小视频,这些视频的播放时间长短不完全相同。现在给定一段时间,你能告诉XP他最多可以看多少个视频吗?每个视频的播放时间和给定的总时间均用分钟为单位。
输入
单组输入数据
第一行为m n
m为给定时间长度(分钟)(0<n,m<=1000)
n表示视频个数
接下来是n个整数代表每个视频的播放时间(每个视频播放时间为不超过1000的正整数)
输出
输出一个整数代表XP最多可以看的视频数。
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int x[1005];

int main()
{//运用贪心思想,将时长最短的视频先看,最后会看到更多
    int n;
    int  all;
    scanf("%d %d",&all,&n);

        int last=0;
        memset(x,0,sizeof(x));
     for(int i=1;i<=n;i++){
        cin>>x[i];
     }
     sort(x+1,x+n+1);
     for(int j=1;j<=n;j++){
        double temp=all-x[j];
        if(temp>=0.0){
                all=temp;
            last++;
        }
     }
     cout<<last<<endl;



    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43520913/article/details/105824464