HIT集训第一天

来源:互联网 发布:mac win触摸板难用 编辑:程序博客网 时间:2024/06/07 06:24

A Joysticks

两个手柄只有一个充电器,不充电的手柄每分钟掉两格电,充电的手柄每分钟加一格电,一开始有一个手柄的电量是1的话那个手柄必须充电,当有一个手柄电量为0的时候游戏就停止了,简单的模拟。

#include<stdio.h> int max(int a,int b){    if(a > b) return a;    else return b;} int min(int a,int b){    if(a < b) return a;    else return b;} int main(){   int a,b;   int ans;   int l,h;   while(~scanf("%d%d",&a,&b))   {       ans=0;       l=min(a,b);       h=max(a,b);       int charge=1;       if(l<2 && h<2)       {           printf("0\n");           continue;       }       while(l>0 && b>0)       {           while(charge==1)           {               if(h==1||h==2)               {                   charge=2;                   break;               }               l++;               h-=2;               ans++;           }           while(charge==2)           {               if(l==1||l==2)               {                   charge = 1;                   break;               }               h++;               l-=2;               ans++;           }           if(h<=2&&l<=2)           {               ans++;               break;           }       }       printf("%d\n",ans);   }   return 0;}



 B Polycarp at the Radio

一个人喜欢的乐队是1-m,他想要他所有喜欢的乐队演出次数最少的那个值最大化。n表示有n首曲子要表演 a[i]表示要表演的乐队

n/m 先算出那个最小的数是多少

统计1-m的个数 

大于m的数都替换掉

当然小于m但是表演次数大于n/m也要替换掉

#include<stdio.h>#include<algorithm>using namespace std;#define N 2001 int a[N],b[N]; int main(){int n,m,l=0;scanf("%d %d",&n,&m);int rec = n / m;for(int i=1 ; i<=n ; i++){scanf("%d",&a[i]);if(a[i] <= m)b[a[i]]++;}//for(int i=1; i<=m ; i++)//printf("%d ",b[i]);//printf("\n");for(int i=1 ; i<=m ; i++){if(b[i] < rec)l += rec - b[i];}for(int i=1 ; i<=n ; i++){if(a[i] > m){for(int j=1 ; j<=m ; j++){if(b[j] < rec){a[i] = j;b[j]++;break;}}}else if(b[a[i]] > rec){for(int j=1 ; j<=m ; j++){if(b[j] < rec){b[a[i]]--;b[j]++;a[i] = j;break;}}}}printf("%d %d\n",rec,l);for(int i=1 ; i<n ; i++)printf("%d ",a[i]); printf("%d\n",a[n]); } 

C Crossing River 

n个人过河,只有一条船,一次只能装两个人,每次过去后还要一个人划回来,过河时间为两个人中速度慢的,求所有人过河最小的时间。

贪心,设a,b,c,d分别为最快,次快,次慢,最慢。那么把c,d送过河去有两种策略。

1. 最快和次快的先过去,最快回来,次慢和最慢过去,次快回来

时间为 b+a+d+b

2. 最快和次慢过去,最快回来,最快和最慢过去,最快回来

时间为 c+a+d+a

应该是每次都要让对岸速度最快的把船开回来,然后人数小于四的话可以直接求得结果的

emmm....其实我自己还是搞不懂这种题,对我来说好难理解。。。

#include<stdio.h>#include<algorithm>using namespace std;#define N 1001 int a[N]; int max(int a,int b){if(a > b) return a;return b;}  int main(){int t;int n;int sum1,sum2;scanf("%d",&t);while(t--){sum1 = 0;sum2 = 0;scanf("%d",&n);for(int i=1 ; i<=n ; i++)scanf("%d",&a[i]);sort(a+1,a+1+n);for(; n>=4 ; n-=2){sum2 += min(a[1] + a[n] + a[n-1] + a[1],a[2] + a[1] + a[n] + a[2]);}if(n == 1){printf("%d\n",a[1]+sum2);continue;}else if(n == 2){printf("%d\n",a[2]+sum2);}else if(n == 3){printf("%d\n",a[1]+a[2]+a[3]+sum2);}}}

D Doing Homework again

有很多作业要做,每个作业都有一个截止时间,如果超过截止时间这个作业没做的话就会扣分,假设做每项作业要一天,问怎么安排才能减最少的分

结构体存下,用数组标记一下每天是否有作业做,按分数从大到小排序,遍历从截止日期到第一天,如果所有天都有作业要做,那么说明这个作业只能放弃,因为是按分数从大到小排序的,从前往后遍历时,前面已近做的作业肯定比现在这个作业扣的分数更多,因此这样算出来的答案是最小的。

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define N 1001 int used[N]; struct pro{int val,dl;}x[N]; bool cmp(pro a,pro b){if(a.val != b.val)return a.val > b.val;else return a.dl > b.dl;} int main(){int t,n,res;scanf("%d",&t);while(t--){res = 0;scanf("%d",&n);memset(used,0,sizeof(used));for(int i=1 ; i<=n ; i++)scanf("%d",&x[i].dl);for(int i=1 ; i<=n ; i++)scanf("%d",&x[i].val);sort(x+1,x+1+n,cmp);//for(int i=1 ; i<=n ; i++)//printf("%d %d\n",x[i].dl,x[i].val);for(int i=1 ; i<=n ; i++){int j=x[i].dl;for( ; j>0 ; j--){if(used[j]==0){used[j] = 1;break;}//if(j == 0)}if(j==0) res += x[i].val;//("j: %d\n",j);//printf("look: %d\n ",x[i].val); }//for(int i=1 ; i<=n ; i++)//printf("%d ",used[i]);printf("%d\n",res);}return 0;}

E  Task

m个任务要完成,每个任务需要xi分钟,难度为yi。同时又n台机器,每个机器有个工作时间wi和等级levi,只有 wi>=xi && levi >=yi时,这个机器才能完成这个任务,每完成一个任务可以获得(500*xi+2*yi)的money。问怎样才能做最对的任务,并且得到最多的钱。

xi占的权重比y大的多 所以把任务按x从大到小排序,先解决前面的任务得到的钱肯定比后面的多。对于怎样完成最多的任务,那么遍历任务,把机器时间大于当前任务的机器都加到一个集合里,然后找出能完成这个任务等级最小的机器,这样的策略是最优的。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#include<set>#define ll long longconst int inf = 0x3f3f3f3f;const int maxn =  100500;struct test{int w,d;}t[maxn],m[maxn];int v[maxn];int cmp(test a,test b){if(a.w!=b.w) return a.w > b.w;else return a.d > b.d;}int main(){ll res,num;int nn,mm;while(~scanf("%d%d",&nn,&mm)){num = res = 0;memset(v,0,sizeof(v));for(int i=0;i<nn;i++)scanf("%d%d",&m[i].w,&m[i].d);for(int i=0;i<mm;i++)scanf("%d%d",&t[i].w,&t[i].d);sort(m,m+nn,cmp);sort(t,t+mm,cmp);for(int i=0,j=0;i<mm;i++){while(j<nn && m[j].w>=t[i].w){v[m[j].d]++;j++;}for(int z=t[i].d;z<=100;z++){if(v[z]) {v[z]--;res += 500*t[i].w + 2*t[i].d;num++;break;}}}printf("%lld %lld\n",num,res);}return 0;}





F Error Curves

简单三分

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define eps 1e-5int n,a1,b1,c1,t;int a[10001],b[10001],c[10001];double max1(double a,double b){    if(a > b) return a;    return b;}double cal(double k){    double res = a[0]* k * k + b[0] * k + c[0];    for(int i=1 ; i<n ; i++)        res = max1(res,a[i] * k * k + b[i] * k + c[i]);    return res;}double solve(){    double l,r,mid,mmid;    l = 0; r = 1000;    mid = (l + r) / 1;    mmid = (mid + r) / 1;    for(int i=0 ; i<=100 ; i++)    {      //  printf("1\n");        if(cal(mid) < cal(mmid)) r = mmid;        else l = mid;        mid = (r + l)/2;        mmid = (mid + r)/2;    }    return cal(l);}int main(){    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i=0 ; i<n ; i++)            scanf("%d%d%d",&a[i],&b[i],&c[i]);        printf("%.4lf\n",solve());    }}

G http://acm.hit.edu.cn/hojx/showcontest/41/G/

二分 我不会


H http://poj.org/problem?id=3258

一条直线,已知起点和终点,中间有些点,只能走给出的点从起点走到终点,二分答案即可。

#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<deque>#include<stack>#include<list>#include<map>#include<vector>using namespace std;#define ll long longconst int maxn = 50500;const int inf = 0x3f3f3f3f; int l,n,m;int a[maxn]; int bs(int l,int r,int k){    while(l<=r)    {        int sub = 0;        int cnt = 0;        int mid = (l+r) >> 1;        for(int i=1;i<=n+1;i++)        {            if(mid >= a[i]-a[sub]) cnt++;                else sub = i;        }        if(cnt > k) r = mid - 1;        else l = mid + 1;    }    return l;} int main(){   while(~scanf("%d%d%d",&l,&n,&m))   {       a[0] = 0;       a[n+1] = l;       for(int i=1;i<=n;i++)        scanf("%d",&a[i]);       sort(a+1,a+n+1);       printf("%d\n",bs(0,l,m));   }}


I http://poj.org/problem?id=3579


不会



J http://acm.hit.edu.cn/hojx/showcontest/40/J/


不会。。。


原创粉丝点击