HDOJ 2025-2140

 

2024C语言合法标识符

Problem Description
输入一个字符串,判断其是否是C的合法标识符。
 
Input
输入数据包含多个测试实例,数据的第一行是一个整数n,表示测试实例的个数,然后是n行输入数据,每行是一个长度不超过50的字符串。
 
Output
对于每组输入数据,输出一行。如果输入数据是C的合法标识符,则输出"yes",否则,输出“no”。
 
Sample Input
3
12ajf
fi8x_a
ff  ai_2
 
Sample Output
no
yes
no

是否何发法的判断标准:如果每个字符数组的第一个字符为非字母或非下划线,则字符串不合法;如果整个字符数组中存在不是字母、数字、下划线的字符,则字符串不合法;

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    int i,j;
    int flag;
    char a[101];
    scanf("%d",&n);
    getchar();
    for(j=0;j<n;j++)
    {
        gets(a);
        if((a[0]>='a'&&a[0]<='z')||(a[0]>='A'&&a[0]<='Z')||(a[0]=='_'))
        {
            flag=1;
            for(i=1;a[i]!='\0';i++)
            {
                if((a[i]>='a'&&a[i]<='z')||(a[i]>='A'&&a[i]<='Z')||(a[i]=='_')||(a[i]>='0'&&a[i]<='9'))
                {
                    flag=1;
                }
                else
                {
                    flag=0;
                    break;
                }
            }
        }
        else flag=0;
        if(flag==0) printf("no\n");
        if(flag==1) printf("yes\n");
    }
}

语法:

①输入n,并用getchar()清空缓存区,建立循环,控制测试次数

在scanf输入n后,回车也被放到了缓冲区,但是scanf读取了回车之前的内容,却把回车符号留在了缓冲区,这就造成缓冲区是有东西的,因而后面的gets(a)直接读取了这个回车符。

 

     把第九行的getchar()注释后运行,得到如下,发现回车被当成了一次输入的字符串,并返回了no

②用gets()给字符数组赋值,用scanf会忽略空格字符。

 https://blog.csdn.net/qq_63519366/article/details/125897779

https://www.jianshu.com/p/415250a15054


2025查找最大元素

Problem Description

对于输入的每个字符串,查找其中的最大字母,在该字母后面插入字符串“(max)”。
 
Input
输入数据包括多个测试实例,每个实例由一行长度不超过100的字符串组成,字符串仅由大小写字母构成。

 

Output
对于每个测试实例输出一行字符串,输出的结果是插入字符串“(max)”后的结果,如果存在多个最大的字母,就在每一个最大字母后面都插入"(max)"。

 

Sample Input
abcdefgfedcba xxxxx
 
Sample Output
abcdefg(max)fedcba x(max)x(max)x(max)x(max)x(max)
#include<bits/stdc++.h>
using namespace std;
int main()
{
    string s;
    int i,len;
    char x;
    while(getline(cin,s))
    {
        x=s[0];
        len=s.size();
        for(i=0;i<len;i++)
        {
            if(s[i]>x) x=s[i];
        }
        for(i=0;i<len;i++)
        {
            printf("%c",s[i]);
            if(s[i]==x) printf("(max)");
        }
        printf("\n");
    }
}

 

语法:输入若干字符串的循环 while(getline(cin,s))

 


2026首字母变大写

Problem Description
输入一个英文句子,将每个单词的第一个字母改成大写字母。
 
Input
输入数据包含多个测试实例,每个测试实例是一个长度不超过100的英文句子,占一行。

 

Output
请输出按照要求改写后的英文句子。

 

Sample Input
i like acm i want to get an accepted

 

Sample Output
I Like Acm
I Want To Get An Accepted

 

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string s;
    int i;
    while(getline(cin,s))
    {
        if(s[0]>='a'&&s[0<='z']) s[0]-=32;
        for(i=1;i<s.size();i++)
        {
            if(s[i-1]==' ') s[i]-=32;
        }
        cout<<s<<endl;
    }
}

 


2027统计元音

Problem Description
统计每个元音字母在字符串中出现的次数。

 

Input
输入数据首先包括一个整数n,表示测试实例的个数,然后是n行长度不超过100的字符串。

 

Output
对于每个测试实例输出5行,格式如下:
a:num1
e:num2
i:num3
o:num4
u:num5
多个测试实例之间由一个空行隔开。请特别注意:最后一块输出后面没有空行:)

 

Sample Input
2
aeiou
my name is ignatius

 

Sample Output
a:1
e:1
i:1
o:1
u:1
 
a:2
e:1
i:3
o:0
u:1
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    int i,j;
    string s;
    scanf("%d",&n);
    getchar();
    int count[5]={0,0,0,0,0};
    for(i=0;i<n;i++)
    {
        getline(cin,s);
        for(j=0;j<s.size();j++)
        {
            if(s[j]=='a') count[0]++;
            else if(s[j]=='e') count[1]++;
            else if(s[j]=='i') count[2]++;
            else if(s[j]=='o') count[3]++;
            else if(s[j]=='u') count[4]++;
        }
        printf("a:%d\n",count[0]);
        printf("e:%d\n",count[1]);
        printf("i:%d\n",count[2]);
        printf("o:%d\n",count[3]);
        printf("u:%d\n",count[4]);
    }

}

 


 


 

Lowest Common Multiple Plus

Problem Description
求n个数的最小公倍数。
 
Input
输入包含多个测试实例,每个测试实例的开始是一个正整数n,然后是n个正整数。
 
Output
为每组测试数据输出它们的最小公倍数,每个测试实例的输出占一行。你可以假设最后的输出是一个32位的整数。
 
Sample Input
2 4 6 3 2 5 7
 
Sample Output
12 70
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    int i,j;
    int x,y,temp;
    int a[1001];
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }

        for(j=0;j<n-1;j++)
        {
            x=a[j];
            y=a[j+1];
           //求最大公约数-------------
            while(x%y!=0)
            {
                temp=x%y;
                x=y;
                y=temp;
            }
           //------------------------------
            a[j+1] = a[j+1]/y*a[j];//求最小公倍数
        }
        printf("%d\n",a[j]);
    }
   
}

方法:两数求最小公倍数,用辗转相除求最大公约数,最小公倍数等于两数乘积除以最大公约数。

思路:多数求最小公倍数:
                   1.先用转转相除法求前两个数的最大公约数a,最小公倍数b=前两个数乘积/最大公约数a,
                   2.再用b和下一个数求得最小公倍数,
                      .......以此类推。
        辗转相除法说明:用两个数中的较大的数a除以较小的数b,得到余数c,再用余数c除以除数b得到新的余数,再用除数b除以新的余数,直到余数为零时,除数则是最大公约数。
      

 

 

       注意!注意!注意!在求最小公倍数时要先除以最大公约数再乘以另外一个数,要不然两个数的乘积可能会超出整型范围。



 


 Palindromes _easy version

Problem Description
“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。请写一个程序判断读入的字符串是否是“回文”。

 

Input
输入包含多个测试实例,输入数据的第一行是一个正整数n,表示测试实例的个数,后面紧跟着是n个字符串。

 

Output
如果一个字符串是回文串,则输出"yes",否则输出"no".

 

Sample Input
4 level abcde noon haha

 

Sample Output
yes no yes no

 

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    int i,j,k;
    string s;
    int flag;
    scanf("%d",&n);
    getchar();
    for(i=0;i<n;i++)
    {
        getline(cin,s);
        int len = s.size();
        if(len%2==0)
        {
            flag=1;
            for(j=len/2-1,k=len/2;j>0,k<len;j--,k++)
            {
                if(s[j]!=s[k])
                {
                    flag=0;
                    break;
                }
            }
        }
        else
        {
            flag=1;
            for(j=len/2-1,k=len/2+1;j>0,k<len;j--,k++)
            {
                if(s[j]!=s[k])
                {
                    flag=0;
                    break;
                }
            }
        }
    if(flag==1) printf("yes\n");
    else printf("no\n");

    }
}

 

 




 汉字统计

 Problem Description

统计给定文本文件中汉字的个数。

 

Input
输入文件首先包含一个整数n,表示测试实例的个数,然后是n段文本。

 

Output
对于每一段文本,输出其中的汉字的个数,每个测试实例的输出占一行。
[Hint:]从汉字机内码的特点考虑~

Sample Input
2
WaHaHa! WaHaHa! 今年过节不说话要说只说普通话WaHaHa! WaHaHa!
马上就要期末考试了Are you ready?

 

Sample Output
14
9

 

#include<bits/stdc++.h>
using namespace std;
// int main()
// {
//     int n;
//     int i,j;
//     string s;
//     int count;
//     scanf("%d",&n);
//     getchar();
//     for(i=0;i<n;i++)
//     {
//         getline(cin,s);
//         count = 0;
//         for(j=0;j<s.size();j++)
//         {
//             if(s[j]<0) count++;
//         }
//         printf("%d\n",(count/2)*2);

//     }
// }
int main()
{
    int count;
    char c;
      count=0; 
        while ((c = getchar()) != '\n')//逐个判断字符,汉字的是两个字符
        {
            if (c < 0)
                count++;
        }

        printf("%d\n", (count / 2)*2);    
    
    return 0;
}

 

①汉字机内码在计算机的表达方式的描述是,使用二个字节,每个字节最高位一位为1,所以在统计结果的时候就要将count除以2了✔
②计算机中,补码第一位是符号位,1 表示为负数,所以汉字机内码的每个字节表示的十进制数都是负数  
所以这题也就可以简化为输入字符串判断其中字符转化为十进制数是否小于零.




 2031进制转换

Problem Description
输入一个十进制数N,将它转换成R进制数输出。

 

Input
输入数据包含多个测试实例,每个测试实例包含两个整数N(32位整数)和R(2<=R<=16, R<>10)。

 

Output
为每个测试实例输出转换后的数,每个输出占一行。如果R大于10,则对应的数字规则参考16进制(比如,10用A表示,等等)。

 

Sample Input
7 2
23 12
-4 3
 
Sample Output
111
1B
-11

 

/*输入一个十进制数N,将它转换成R进制数输出。R(2<=R<=16, R!=10) */

#include <bits/stdc++.h>
#define LL long long
using namespace std;
int main()
{
    LL m, n;
    int ans[1001];
    int i, j;
    int flag;
    while (cin >> n >> m)
    {
        flag = 1;
        int y = n;
        if (n < 0)
        {
            flag = 0;
            n = -n;
        }
        if (n == 0)
        {
            cout << 0 << endl;
            continue;
        }
        j = 1;
        while (n)
        {
            ans[j++] = n % m;
            n /= m;
        }
        if (flag == 0)
            cout << '-';
        for (i = j - 1; i >= 1; --i)
        {
            if (m >= 10 && ans[i] >= 10)
                cout << char(55 + ans[i]);
            else
                cout << ans[i];
        }
        cout << endl;
    }
}

 

①for循环中 i++ 和 ++i 的使用效果是一样的;for循环中 i++的耗时比++i的要长一些。数据量大些时候就比较明显了;
②a[i++]是先取a[i]的值.然后i再自加

 


 

 2032杨辉三角

Problem Description
还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考以下的图形:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
 
Input
输入数据包含多个测试实例,每个测试实例的输入只包含一个正整数n(1<=n<=30),表示将要输出的杨辉三角的层数。
 
Output
对应于每一个输入,请输出相应层数的杨辉三角,每一层的整数之间用一个空格隔开,每一个杨辉三角后面加一个空行。
 
Sample Input
2 3
 
Sample Output
1 1 1 1 1 1 1 2 1
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    int i,j;
    int a[31][31];
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0;i<n;i++)
        {
            if(i==0) 
            {
                printf("1\n");
                a[0][0]=1;
            }
            else if(i==1)
            {
                printf("1 1\n");
                a[1][0]=1;
                a[1][1]=1;
            }
            else
            {
                a[i][0]=1;
                a[i][i]=1;
                for(j=1;j<=i-1;j++)
                {
                    a[i][j]=a[i-1][j]+a[i-1][j-1];
                }
                for(j=0;j<i+1;j++)
                {
                    printf("%d ",a[i][j]);
                }
                printf("\n");

            }
        }
    }
}
// 1
// 1 1
// 1 2 1 i=2
// 1 3 3 1
// 1 4 6 4 1
// 1 5 10 10 5 1

 


 

2033人见人爱A+B

Problem Description
HDOJ上面已经有10来道A+B的题目了,相信这些题目曾经是大家的最爱,希望今天的这个A+B能给大家带来好运,也希望这个题目能唤起大家对ACM曾经的热爱。
这个题目的A和B不是简单的整数,而是两个时间,A和B 都是由3个整数组成,分别表示时分秒,比如,假设A为34 45 56,就表示A所表示的时间是34小时 45分钟 56秒。
 
Input
输入数据有多行组成,首先是一个整数N,表示测试实例的个数,然后是N行数据,每行有6个整数AH,AM,AS,BH,BM,BS,分别表示时间A和B所对应的时分秒。题目保证所有的数据合法。
 
Output
对于每个测试实例,输出A+B,每个输出结果也是由时分秒3部分组成,同时也要满足时间的规则(即:分和秒的取值范围在0~59),每个输出占一行,并且所有的部分都可以用32位整数表示。
 
Sample Input
2 1 2 3 4 5 6 34 45 56 12 23 34
 
Sample Output
5 7 9 47 9 30

 

 

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    int i, j;
    scanf("%d", &n);
    int a[6];
    int b[3];
    while (n > 0)
    {
        for (i = 0; i < 6; i++)
        {
            scanf("%d", &a[i]);
        }

        b[2] = (a[2] + a[5]) % 60;//
        b[1] = (a[1] + a[4]+(a[2] + a[5])/60)% 60;//
        b[0] = (a[0] + a[3]+(a[1] + a[4]+(a[2] + a[5])/60)/60);//
        
        printf("%d %d %d\n", b[0], b[1], b[2]);
        n--;
    }
}

 


 

2034人见人爱A-B

Problem Description
参加过上个月月赛的同学一定还记得其中的一个最简单的题目,就是{A}+{B},那个题目求的是两个集合的并集,今天我们这个A-B求的是两个集合的差,就是做集合的减法运算。(当然,大家都知道集合的定义,就是同一个集合中不会有两个相同的元素,这里还是提醒大家一下)
呵呵,很简单吧?
 
Input
每组输入数据占1行,每行数据的开始是2个整数n(0<=n<=100)和m(0<=m<=100),分别表示集合A和集合B的元素个数,然后紧跟着n+m个元素,前面n个元素属于集合A,其余的属于集合B. 每个元素为不超出int范围的整数,元素之间有一个空格隔开.
如果n=0并且m=0表示输入的结束,不做处理。
 
Output
针对每组数据输出一行数据,表示A-B的结果,如果结果为空集合,则输出“NULL”,否则从小到大输出结果,为了简化问题,每个元素后面跟一个空格.
 
Sample Input
3 3 1 2 3 1 4 7 3 7 2 5 8 2 3 4 5 6 7 8 0 0
 
Sample Output
2 3 NULL
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n, m;
    int a[101], b[101];
    int i, j;
    int flag;
    while (scanf("%d %d", &m, &n) != EOF)
    {
        if (m == 0 && n == 0)
            return 0;
        flag = 0;
        for (i = 0; i < m; i++)
            scanf("%d", &a[i]);
        for (j = 0; j < n; j++)
            scanf("%d", &b[j]);
        for (i = 0; i < m; i++)
        {
            for (j = 0; j < n; j++)
            {
                if (a[i] == b[j])
                {
                    a[i] = -1;
                    break;
                }
            }
        }
        for (i = 0; i < m; i++)
        {
            if (a[i] < 0)
                flag++;
        }
        if (flag == m)
            printf("NULL");
        else
        {
            for (i = 0; i < m; i++)
            {
                if (a[i] != -1)
                    printf("%d ", a[i]);
            }
        }
        printf("\n");
    }
}


2035人见人爱A^B

Problem Description

求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”
 
Input
输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。

 

Output
对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。
 
Sample Input
2 3 12 6 6789 10000 0 0
 
Sample Output
8
984
1
e.g. one:
    
输入数据:123 2

即计算: 123 * 123 = 15,129   后三位:129

竖式:             
                   1 2 3
                 * 1 2 3
                ——————————
                   3 6 9
                 2 4 6 0
               1 2 3 0 0
               ———————————
               1 5,1 2 9

e.g. two:
    
输入数据: 6789 3

即计算: 6789 * 6789 * 6789 = 312,908,547,069‬  后三位:069

竖式:              
                   6,7 8 9
                *  6,7 8 9 
                ————————————
                 6 1,1 0 1
               5 4 3,1 2 0
             4 7 5 2,3 0 0
           4 0 7 3 4,0 0 0
           —————————————————
           4 6 0 9 0,5 2 1*         6,7 8 9   //此处我偷个懒,可以自行补充
   —————————————————————————
   3 1 2 9 0 8 5 4 7,0 6 9
   
综上所述:当计算的数据超过3位数时,只需用数据的后三位进行计算即可

 

 方法一:采用准暴力方法求解,即每乘一次该数取最后3位, 然后用这最后3位继续乘以这个数继续取最后3位,一直到最后即可求出答案
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int A, B, t;
    int i;
    while (cin >> A >> B)
    {
        if (A == 0 && B == 0)
            return 0;
        i = 1;
        t = A % 1000; // 后3位数
        while (i <= B - 1)
        {
            t = (t * A) % 1000;
            i++;
        }
        cout << t<< endl;
    }
    return 0;
}

 方法二:若此题A,B的范围变为(1<=A,B<=100 000 000)那么如果采用此方法,一定会超时。因此此题采用快速幂运算能够更好的解决此题。

 

 

int power(int a,int n)////递归实现
{
    int ans;
    if(n==0) ans=1; // 结束条件 
    else 
    {
        ans=power(a*a,n/2); // 递归调用 
        if(n%2==1) ans*=a; // n为奇数 
    }
    return ans;
}

int power(int a,int n)////非递归实现
    {
        int ans=1;
        while(n)
        { 
            if(n%2) ans=ans*a; // 奇数情况
            a=a*a; // 底数平方
            n=n/2; // 指数减半 
        }
        return ans;
    }

使用快速幂运算的代码:

#include<iostream>
using namespace std;
 
int power(int a,int n)
{
    int ans=1;
    while(n)
    { 
        if(n%2) ans=(ans*a)%1000; // 奇数情况
        a=(a*a)%1000; // 底数平方取后3位
        n=n/2; // 指数减半
    }
    return ans;
}
 
int main()
{
    int A,B;
    while(cin>>A>>B)
    {
    if(A==0 && B==0) return 0;
    cout<<power(A,B)<<endl;
    }
    return 0;
}

 


2036改革春风吹满地

Problem Description
“ 改革春风吹满地,
不会AC没关系;
实在不行回老家,
还有一亩三分地。
谢谢!(乐队奏乐)”
话说部分学生心态极好,每天就知道游戏,这次考试如此简单的题目,也是云里雾里,而且,还竟然来这么几句打油诗。
好呀,老师的责任就是帮你解决问题,既然想种田,那就分你一块。
这块田位于浙江省温州市苍南县灵溪镇林家铺子村,多边形形状的一块地,原本是linle 的,现在就准备送给你了。不过,任何事情都没有那么简单,你必须首先告诉我这块地到底有多少面积,如果回答正确才能真正得到这块地。
发愁了吧?就是要让你知道,种地也是需要AC知识的!以后还是好好练吧...
 
Input
输入数据包含多个测试实例,每个测试实例占一行,每行的开始是一个整数n(3<=n<=100),它表示多边形的边数(当然也是顶点数),然后是按照逆时针顺序给出的n个顶点的坐标(x1, y1, x2, y2... xn, yn),为了简化问题,这里的所有坐标都用整数表示。
输入数据中所有的整数都在32位整数范围内,n=0表示数据的结束,不做处理。
 
Output
对于每个测试实例,请输出对应的多边形面积,结果精确到小数点后一位小数。
每个实例的输出占一行。
 
Sample Input
3 0 0 1 0 0 1
4 1 0 0 1 -1 0 0 -1
0
 
Sample Output
0.5
2.0

 

 


2037今年暑假不AC

Problem Description

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

 

Output
对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。
 
Sample Input
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0
 
Sample Output
5
贪心算法:活动安排问题
问题描述:设有n个活动的集合E={1,2,3...n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源
>每个活动i都有一个要求使用该资源的起始时间si,和一个结束时间fi,且si,<fi
>如果选择了活动i,则它在[si, fi)内占用资源。
>若[si, fi)与[sj, fj)不相交,则称活动i与j是相容的。
>活动安排问题就是求E的最大相容活动子集。
解决思路:用数组s,f,A分别存放所有活动的 起始时间、结束时间、是否予以安排 的标记。
 某项活动结束时间愈早,安排其它活动的剩余区间愈大。算法贪心选择的意义是使剩余的可安排时间段极大化,以便安排尽可能多的相容活动。
 为此,将数组中的活动按结束时间的非减顺序排序,即f1≤f2,<...fn。显然排序需要的时间为O(nlogn)。
GreedyAlgorithm(parameters)
{
初始化;
重复执行以下的操作:
选择当前可以选择的最优解;
将所选择的当前解加入到问题的解中去;
直至满足问题求解的结束条件。
}

template <class Type>
void GreedySelectox(int n, Type s[], Type f[], bool A[])
{
    A[1] = true;//序号从1开始记录,排序后的第一个节目肯定第一个看
    int j = 1;
    for (int i = 2; i <= n; i++)//for循环比较剩下n-1个节目
    {
        if (s[i] >= f[j])//在其之后,可以安排
        {
            A[i] = true;
            j = i;
        }
        else//在其之前开始,不能安排
            A[i] = false;
    }
}

 

 

 

 可以选择的活动是:1 2 6 9 11,共五个

 归纳:●贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择(即贪心选择)来达到。
       这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
      ●动态规划算法通常以自底向上的方式解各子问题
      ●贪心算法则通常以自顶向下的方式进行,以迭代方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
      ●对具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
      ●当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。


 


 

2039三角形

Problem Description
给定三条边,请你判断一下能不能组成一个三角形。
 
Input
输入数据第一行包含一个数M,接下有M行,每行一个实例,包含三个正数A,B,C。其中A,B,C <1000;
 
Output
对于每个测试实例,如果三条边长A,B,C能组成三角形的话,输出YES,否则NO。
 
Sample Input
2 1 2 3 2 2 2
 
Sample Output
NO YES
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    int a[3];
    int i, j;
    scanf("%d", &n);

    for (j = 0; j < n; j++)
    {
        for (i = 0; i < 3; i++)
        {
            scanf("%d", &a[i]);
        }
        if ((a[0] + a[1]) > a[2] && (a[0] + a[2]) > a[1] && a[1] + a[2] > a[0])
        {
            printf("YES\n");
        }
        else
            printf("NO\n");
    }
}

2040亲和数

Problem Description
古希腊数学家毕达哥拉斯在自然数研究中发现,220的所有真约数(即不是自身的约数)之和为:
1+2+4+5+10+11+20+22+44+55+110=284。
而284的所有真约数为1、2、4、71、 142,加起来恰好为220。人们对这样的数感到很惊奇,并称之为亲和数。一般地讲,如果两个数中任何一个数都是另一个数的真约数之和,则这两个数就是亲和数。
你的任务就编写一个程序,判断给定的两个数是否是亲和数
 
Input
输入数据第一行包含一个数M,接下有M行,每行一个实例,包含两个整数A,B; 其中 0 <= A,B <= 600000 ;
 
Output
对于每个测试实例,如果A和B是亲和数的话输出YES,否则输出NO。
 
Sample Input
2 220 284 100 200

Sample Output
YES NO

核心:求约数/判素数

#include <bits/stdc++.h>
using namespace std;
int func(int x)
{
    int ret = 0;
    int p = 0;
    for (int i = 1; i < sqrt(x); i++)
    {
        if (x % i == 0)
        {
            p = x / i;
            ret += i;
            ret += p;
            // 一次整除获得两个约数
        }
    }
    ret -= x; // 减去自身
    return ret;
}

int main()
{
    int n;
    scanf("%d", &n);
    int i;
    int x, y;
    for (i = 0; i < n; i++)
    {
        scanf("%d %d", &x, &y);
        if (func(x) == y && func(y) == x)
            printf("YES\n");
        else printf("NO\n");
    }
}

 


 


 

posted @ 2023-02-21 19:38  EleclouD  阅读(62)  评论(1编辑  收藏  举报