HDU1264、1280、1425、1496、1800(简单哈希练习)

Counting Squares

 

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2439    Accepted Submission(s): 1184

 

 

Problem Description

Your input is a series of rectangles, one per line. Each rectangle is specified as two points(X,Y) that specify the opposite corners of a rectangle. All coordinates will be integers in the range 0 to 100. For example, the line
5 8 7 10
specifies the rectangle who's corners are(5,8),(7,8),(7,10),(5,10).
If drawn on graph paper, that rectangle would cover four squares. Your job is to count the number of unit(i.e.,1*1) squares that are covered by any one of the rectangles given as input. Any square covered by more than one rectangle should only be counted once.

 

 

Input

The input format is a series of lines, each containing 4 integers. Four -1's are used to separate problems, and four -2's are used to end the last problem. Otherwise, the numbers are the x-ycoordinates of two points that are opposite corners of a rectangle.

 

 

Output

Your output should be the number of squares covered by each set of rectangles. Each number should be printed on a separate line.

 

 

Sample Input

 

5 8 7 10 6 9 7 8 6 8 8 11 -1 -1 -1 -1 0 0 100 100 50 75 12 90 39 42 57 73 -2 -2 -2 -2

 

 

Sample Output

 

8 10000

 

题目大意:以-1截止为一组数据,每组数据有多对点,每行2个点,表示矩形的左上角点坐标和右下角坐标,求每组矩形覆盖的面积。输入-2时结束。

 

思路:哈希运用?感觉像是小技巧,数据很小,可直接设地图,然后遍历,若覆盖便更新数据。

 

代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
int p[105][105];
using namespace std;
int main()
{
    int a,b,c,d,i,j,s=0,t;
    while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF)
    {
        if(a==-1)
        {
            memset(p,0,sizeof(p));
            printf("%d\n",s);
            s=0;
            continue;
        }
        if(a==-2)
        {
            printf("%d\n",s);
            break;
        }
        if(a>c) { t=a,a=c,c=t;}
        if(b>d) { t=b,b=d,d=t;}
        for(i=a+1;i<=c;i++)
        {
            for(j=b+1;j<=d;j++)
            {
                if(p[i][j]==0)
                {
                    p[i][j]=1;
                    s++;
                }
            }
        }
    }
    return 0;
} 

前m大的数

 

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 23194    Accepted Submission(s): 7839

 

 

Problem Description

还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大的M个数告诉她就可以了。
给定一个包含N(N<=3000)个正整数的序列,每个数不超过5000,对它们两两相加得到的N*(N-1)/2个和,求出其中前M大的数(M<=1000)并按从大到小的顺序排列。

 

 

Input

输入可能包含多组数据,其中每组数据包括两行:
第一行两个数N和M,
第二行N个数,表示该序列。
 

 

 

Output

对于输入的每组数据,输出M个数,表示结果。输出应当按照从大到小的顺序排列。

 

 

Sample Input

 

4 4 1 2 3 4 4 5 5 3 6 4

 

 

Sample Output

 

7 6 5 5 11 10 9 9 8

 

思路:哈希?。。。数据这么小,暴力吧。

 

代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<set>
#include<math.h>
int p[3005],p1[10005]={0};
using namespace std;
int main()
{
    int n,m,i,j,k;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        k=0;
        memset(p,0,sizeof(p));
        memset(p1,0,sizeof(p1));
        for(i=0;i<n;i++)
        {
            scanf("%d",&p[i]);
        }
        for(i=0;i<n;i++)
        {
            for(j=i+1;j<n;j++)
            {
                p1[p[i]+p[j]]++;
            }
        }
        int fag=0;
        for(i=10000;i>=0;i--)
        {
            if(p1[i]!=0&&fag==0)
            {
                while(p1[i]!=0)
                {
                    printf("%d",i);
                    p1[i]--;k++;
                    if(k==m) { fag=1;break;}
                    printf(" ");
                }
            }
        }
        printf("\n");
    }
    return 0;
} 

sort

 

Time Limit: 6000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 58157    Accepted Submission(s): 16098

 

 

Problem Description

给你n个整数,请按从大到小的顺序输出其中前m大的数。

 

 

Input

每组测试数据有两行,第一行有两个数n,m(0<n,m<1000000),第二行包含n个各不相同,且都处于区间[-500000,500000]的整数。

 

 

Output

对每组测试数据按从大到小的顺序输出前m大的数。

 

 

Sample Input

 

5 3 3 -35 92 213 -644

 

 

Sample Output

 

213 92 3

思路:数据10^6,暴力?好像不行吧...........但是就是暴力能过....大概是sort O(n*logn),还是数据弱?

 

代码如下:

#include<stdio.h>
#include<algorithm>
using namespace std;
int s[2000000];
bool cmp(int a,int b)
{
    return a>b;
}
int main()
{
    int n,m,i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=0;i<n;i++)
             scanf("%d",&s[i]);
        sort(s,s+n,cmp);
        for(i=0;i<m;i++)
        {
            if(i==m-1)
             printf("%d\n",s[i]);
            else
              printf("%d ",s[i]);
        }
    }
    return 0;
}

Equations

 

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9403    Accepted Submission(s): 3909

 

 

Problem Description

Consider equations having the following form:

a*x1^2+b*x2^2+c*x3^2+d*x4^2=0
a, b, c, d are integers from the interval [-50,50] and any of them cannot be 0.

It is consider a solution a system ( x1,x2,x3,x4 ) that verifies the equation, xi is an integer from [-100,100] and xi != 0, any i ∈{1,2,3,4}.

Determine how many solutions satisfy the given equation.

 

 

Input

The input consists of several test cases. Each test case consists of a single line containing the 4 coefficients a, b, c, d, separated by one or more blanks.
End of file.

 

 

Output

For each test case, output a single line containing the number of the solutions.

 

 

Sample Input

 

1 2 3 -4 1 1 1 1

 

 

Sample Output

 

39088 0

 

题目大意:给出一个四元方程,四个未知数的数据范围为正负100,多组数据输入系数a,b,c,d;输出每组的解个数。

 

思路:如果考虑暴力,四重for循环,遍历-100到100;10^2^4=10^8,差不多接触到底线了,抱着侥幸的心理暴力,虽然限时3s,妥妥的超时。然后考虑优化的问题,个人认为,哈希是一种优化的方法,着重用于处理数据,优化代码速率。我使用的是一种比较普通的方法。对半折开,一半存可选择项,一半直接匹配,算是使用了哈希的思想,借化解冲突的方法减少匹配。

 

代码如下:

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
#define MS 1000005
int s[2000005];
int main() 
{
    int a,b,c,d;
    while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF) 
    {
        if((a>0&&b>0&&c>0&&d>0)||(a<0&&b<0&&c<0&&d<0)) 
        {
            printf("0\n");
            continue;
        }
        for(int i=0;i<MS*2;i++) s[i]=0; 
        for(int i=-100;i<=100;i++) 
        {
            if(i!=0)
                for(int j=-100;j<=100;j++) 
                {
                    if(j!=0)
                    {
                        int x=a*i*i+b*j*j;
                        s[x+MS]++;//该情况可匹配的个数 
                    }
                }
        }
        int sum=0;
        for(int i=-100;i<=100;i++) 
        {
            if(i!=0)
                for(int j=-100;j<=100;j++) 
                {
                    if(j!=0) 
                    {
                        int x=c*i*i+d*j*j;
                        sum+=s[MS-x];//能该情况能完成匹配的数累加 
                    }
                }
        }
        printf("%d\n",sum);
    }
    return 0;
}

Flying to the Mars

 

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 23521    Accepted Submission(s): 7524

 

 

Problem Description


In the year 8888, the Earth is ruled by the PPF Empire . As the population growing , PPF needs to find more land for the newborns . Finally , PPF decides to attack Kscinow who ruling the Mars . Here the problem comes! How can the soldiers reach the Mars ? PPF convokes his soldiers and asks for their suggestions . “Rush … ” one soldier answers. “Shut up ! Do I have to remind you that there isn’t any road to the Mars from here!” PPF replies. “Fly !” another answers. PPF smiles :“Clever guy ! Although we haven’t got wings , I can buy some magic broomsticks from HARRY POTTER to help you .” Now , it’s time to learn to fly on a broomstick ! we assume that one soldier has one level number indicating his degree. The soldier who has a higher level could teach the lower , that is to say the former’s level > the latter’s . But the lower can’t teach the higher. One soldier can have only one teacher at most , certainly , having no teacher is also legal. Similarly one soldier can have only one student at most while having no student is also possible. Teacher can teach his student on the same broomstick .Certainly , all the soldier must have practiced on the broomstick before they fly to the Mars! Magic broomstick is expensive !So , can you help PPF to calculate the minimum number of the broomstick needed .
For example :
There are 5 soldiers (A B C D E)with level numbers : 2 4 5 6 4;
One method :
C could teach B; B could teach A; So , A B C are eligible to study on the same broomstick.
D could teach E;So D E are eligible to study on the same broomstick;
Using this method , we need 2 broomsticks.
Another method:
D could teach A; So A D are eligible to study on the same broomstick.
C could teach B; So B C are eligible to study on the same broomstick.
E with no teacher or student are eligible to study on one broomstick.
Using the method ,we need 3 broomsticks.
……

After checking up all possible method, we found that 2 is the minimum number of broomsticks needed.

 

 

Input

Input file contains multiple test cases.
In a test case,the first line contains a single positive number N indicating the number of soldiers.(0<=N<=3000)
Next N lines :There is only one nonnegative integer on each line , indicating the level number for each soldier.( less than 30 digits);

 

 

Output

For each case, output the minimum number of broomsticks on a single line.

 

 

Sample Input

 

4 10 20 30 04 5 2 3 4 3 4

 

 

Sample Output

 

1 2

 

题目大意:士兵飞火星,需要学骑魔法扫把,每个士兵学习能力有高低,高的能够教导低的共用一把扫把。可以没有老师和学生,求所需的最少扫把数。

 

 

思路:求最多重复数,因为最多出现的与最高、最低都只需一把扫把,再使用map容器和迭代器。(看了下网上的题解,解题方法非常多,字典树,贪心.....不懂,暂时没练到那些专题)。

 

代码如下:

#include<cstdio>
#include<iostream>
#include<map>
using namespace std;
int main()
{
    int n,v,maxs;
    while(scanf("%d",&n)!=EOF)
    {
        maxs=-155;
        map<int,int>m;//第一个为关键字,第二个为关键字的值
        while(n--)
        {
            scanf("%d",&v);
            m[v]++;
        }
        for(map<int,int>::iterator it=m.begin();it!=m.end();it++)
        {
            if(it->second>maxs)
            {
                maxs=it->second;
            }
        }
        cout<<maxs<<endl;
    }
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值