HLJU——15级寒假培训3 题解

A - Choosing Teams

题意:问能组成多少支队伍,满足每支队伍三个人,并且能去k次比赛(上限5次)。

排序后,正常选。


#include<cstdio>
#include<algorithm>
using namespace std;
int a[2100];
int main()
{
    int n,k;
     while(~scanf("%d%d",&n,&k)){
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        sort(a,a+n);
        int t=0;
        for(int i=2;i<n;i+=3){
            if(a[i]+k<=5){
                t++;
            }
        }
        printf("%d\n",t);
     }
}
B -Best Cow Line

题意:依次从头尾删字符,组成字典序最小的新串。

头尾选择字典序小的,相等就继续找。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
char a[2100];
int main()
{
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++){
           cin>>a[i];
        }
        int l=0,r=n-1,t=0;
        while(l<=r){
            int flag=0;
            for(int i=0;i+1<=r;i++){
                if(a[l+i]<a[r-i]){
                    flag=1;
                    break;
                }
                else if(a[l+i]>a[r-i]){
                    flag=0;
                    break;
                }
            }
           if(flag){
               cout<<a[l++];
           }
           else cout<<a[r--];
           t++;
           if(t==80){
                cout<<endl;
                t=0;
           }
        }
    }
}
C -ZCC Loves Codefires

题意:做每道题需要时间,而且时间会推移累加,罚时是时间乘以分数,问总罚时最少是。

贪心策略:优先选择罚分/罚时大的题做。注意long long


#include<bits/stdc++.h>
using namespace std;
struct node
{
    long long t,v;
}a[100100];
bool cmp(node a,node b)
{
  return a.v*b.t>b.v*a.t;
}
int main()
{
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++){
            scanf("%lld",&a[i].t);
        }
        for(int i=0;i<n;i++){
            scanf("%lld",&a[i].v);
        }
        sort(a,a+n,cmp);
        long long res=0,t=0;
        for(int i=0;i<n;i++){
            t+=a[i].t;
            res+=t*a[i].v;
        }
        printf("%lld\n",res);
    }

}

D - Doing Homework again

题意:每个作业有规定时间,和分数,没有按照规定时间内完成的作业,要被扣分数。

这题两个策略:先做分数大的作业,并且按最后规定时间做,不能就向前推移。


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int visit[1010];
struct Node
{
    int t,e;
}node[1010];

bool cmp(Node a,Node b)
{
   return a.e>b.e||a.e==b.e&&a.t>b.t;
}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        memset(visit,0,sizeof(visit));
        int n;scanf("%d",&n);
        for(int i=0;i<n;i++){ scanf("%d",&node[i].t);};
        for(int i=0;i<n;i++) scanf("%d",&node[i].e);
        sort(node,node+n,cmp);
        int ans=0;
        for(int i=0;i<n;i++)
        {
           int  flag=0;
           for(int j=node[i].t;j>0;j--)
           {
               if(visit[j]==0)
               {
                   flag=1;
                   visit[j]=1;
                   break;
               }
           }
           if(!flag) ans+=node[i].e;
        }
        printf("%d\n",ans);
    }
}

E - Tian Ji -- The Horse Racing

题意:和历史上故事情景一模一样。

思路

一、当田忌最快的马比国王最快的马快时,用田忌最快的马赢国王最快的马。(赢的最有价值)
二、当田忌最快的马比国王最快的马慢时,用田忌最慢的马输给国王最快的马。(输的最有价值)
三、当田忌最快的马跟国王最快的马一样快时,如果田忌最慢的马比国王最慢的马还要快,直接比。如果不是,就让田忌最慢的马与国王最快的马比。(解释:这里有一种情况 是田忌最慢的马和国王最慢的马平时,不如让田忌最慢的马和国王最快的马比,两种情况结果都是输一次,但是这里牺牲田忌最慢的马区消耗 国王最快的马,更有价值。)

#include<cstdio>
#include<algorithm>
using namespace std;
int t[1010],k[1010];
bool cmp(int a,int b)
{
    return a>b;
}
int main()
{
    int n;
    while(scanf("%d",&n)&&n)
    {
        for(int i=0;i<n;i++) scanf("%d",&t[i]);
        for(int i=0;i<n;i++) scanf("%d",&k[i]);
        sort(t,t+n,cmp);sort(k,k+n,cmp);
        int t_fast=0,t_slow=n-1,k_fast=0,k_slow=n-1,win=0,lose=0;
        while(t_fast<=t_slow)
        {
            if(t[t_fast]>k[k_fast])
            {
                win++;
                t_fast++;
                k_fast++;
            }
            else if(t[t_fast]<k[k_fast])
            {
                lose++;
                k_fast++;
                t_slow--;
            }
            else
            {
                if(t[t_slow]>k[k_slow])
                {
                    win++;
                    t_slow--;
                    k_slow--;
                }
                else
                {
                    if(t[t_slow]<k[k_fast])
                        lose++;
                    t_slow--;
                    k_fast++;
                }
            }
        }
        printf("%d\n",(win-lose)*200);
    }
}


F - Proud Merchants

01背包的变形

题意:买东西,每个东西有三个特征值,p代表价格,q代表你手中钱必须不低于q才能买这个物品,v代表得到的价值。

mark:又是变种01背包,每做一个变种的,就是一种提高。。

   这题因为涉及到q,所以不能直接就01背包了。因为如果一个物品是5 9,一个物品是5 6,对第一个进行背包的时候只有dp[9],dp[10],…,dp[m],再对第二个进行背包的时候,如果是普通的,应该会借用前面的dp[8],dp[7]之类的,但是现在这些值都是0,所以会导致结果出错。
于是要想到只有后面要用的值前面都可以得到,那么才不会出错。设A:p1,q1 B:p2,q2,如果先A后B,则至少需要p1+q2的容量,如果先B后A,至少需要p2+q1的容量,那么就是p1+q2 > p2+q1,变形之后就是q1-p1 < q2-p2。

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int p,q,v;
}a[555];
int cmp(node a,node b)
{
    return a.q-a.p<b.q-b.p;
}
int dp[5555];
int main()
{
    #ifdef yxj
    freopen("F:\\in.txt","r",stdin);
    #endif // yxj
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<n;i++) scanf("%d %d %d",&a[i].p,&a[i].q,&a[i].v);
        sort(a,a+n,cmp);
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++)
            for(int j=m;j>=a[i].q;j--)
            dp[j]=max(dp[j],dp[j-a[i].p]+a[i].v);

        printf("%d\n",dp[m]);
    }
}



G - Bone Collector  标准的01背包

#include<cstring>
#include<climits>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<stack>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1010;
int dp[maxn],v[maxn],w[maxn];
int main()
{
    int T;cin>>T;
    while(T--){
        memset(dp,0,sizeof(dp));
        int n,W;cin>>n>>W;
        for(int i=0;i<n;i++) cin>>v[i];
        for(int i=0;i<n;i++) cin>>w[i];
        for(int i=0;i<n;i++)
           for(int j=W;j>=w[i];j--)
           dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        cout<<dp[W]<<endl;
    }
}


H - 数塔



#include<bits/stdc++.h>
using namespace std;
int dp[110][110],M[110][110];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;scanf("%d",&n);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=i;j++)
            scanf("%d",&M[i][j]);
        for(int i=1;i<=n;i++) dp[n][i]=M[n][i];
        for(int i=n-1;i>0;i--)
            for(int j=1;j<=i;j++)
            dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+M[i][j];
        printf("%d\n",dp[1][1]);
    }
    return 0;
}

I - Max Sum

最大子段和,需要记载坐标。


本题的状态方程:sum = sum > 0 ? sum+a:a; 
*/ 
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
    int T;
    scanf("%d",&T);
    for(int step=1;step<=T;step++)
    {
        int n,s,e,k,sum=0,Max=-1000;
        s=e=k=1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int a;
            scanf("%d",&a);
            sum+=a;
            if(sum>Max)
            {
                s=k;
                e=i;
                Max=sum;
            }
            if(sum<0)
            {
                sum=0;
                k=i+1;
            }
        }
        if(step!=1) printf("\n");
        printf("Case %d:\n",step);
        printf("%d %d %d\n",Max,s,e);
    }
}

J - 母牛的故事

推出递推方程式:a[i]=a[i-1]+a[i-3];

<span style="font-size:14px;">#include<cstdio>
#include<algorithm>
using namespace std;
int  a[100];
int main()
{
  int n;
  a[1]=1;
  a[2]=2;
  a[3]=3;
  a[4]=4;
  for(int i=5;i<=55;i++)
    a[i]=a[i-1]+a[i-3];
  while(~scanf("%d",&n)&&n)
  {
      printf("%d\n",a[n]);
  }
  return 0;
}</span>


K - Common Subsequence

标准最长公共子序列。

#include<bits/stdc++.h>
using namespace std;
char s1[1010],s2[1010];
int M[1010][1010];
int main()
{
    while(~scanf("%s %s",s1,s2))
    {
        memset(M,0,sizeof(M));
        int n=strlen(s1);
        int m=strlen(s2);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            if(s1[i-1]==s2[j-1])
              M[i][j]=M[i-1][j-1]+1;
            else
              M[i][j]=max(M[i-1][j],M[i][j-1]);
        printf("%d\n",M[n][m]);
    }
    return 0;
}

L - Super Jumping! Jumping! Jumping!

标准最长上升子序列



#include<bits/stdc++.h>
using namespace std;
int a[1010],dp[1010];
int main()
{
    int n;
    while(~scanf("%d",&n)&&n)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            dp[i]=a[i];
        }
        for(int i=1;i<n;i++)
            for(int j=0;j<i;j++)
            if(a[i]>a[j])
            dp[i]=max(dp[i],dp[j]+a[i]);
        printf("%d\n",*max_element(dp,dp+n));
    }
}

M - Milking cows

题意:0 牛向左看,1牛向右看,问怎么杀牛,让牛的总惊吓度最低(每有一头牛看到自己同胞被杀,惊吓度加一)

贪心策略:从左往右把向右看的牛杀掉,再从左向右,把所有向左看的牛杀掉(没有惊吓)。


#include<cstdio>
int main()
{
    int n;
    long long ans=0,sum=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        long long a;
        scanf("%lld",&a);
        if(a)
            ans++;
        else
            sum+=ans;
    }
    printf("%lld\n",sum);
    return 0;
}

N - 今年暑假不AC

活动时间安排问题。

贪心策略:按结束时间排序。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1000005;
int inf=0x3f3f3f3f;
LL mod=1e9+7;
struct Node
{
    int s,e;
}node[110];
bool cmp(Node a,Node b)
{
    return a.e==b.e? a.s<b.s:a.e<b.e;
}
int main()
{
    int n;
    while(cin>>n&&n)
    {
      for(int i=0;i<n;i++) cin>>node[i].s>>node[i].e;
      sort(node,node+n,cmp);
      int ans=0,t=0;
      for(int i=0;i<n;i++)
      {
          if(t<=node[i].s)
          {
              t=node[i].e;
              ans++;
          }
      }
      cout<<ans<<endl;
    }
}





下面是一个使用Verilog语言驱动LCD1602显示"HLJU, I LOVE U!"的示例代码: ``` module lcd1602( input clk, input rst_n, input [7:0] data, input rs, input rw, output enable, output [15:0] lcd_data ); // 内部信号定义 reg [7:0] lcd_buffer [0:31]; reg [5:0] addr; reg write_enable; // 初始化内部信号 initial begin addr = 0; write_enable = 0; lcd_buffer[0] = 8'h48; // H lcd_buffer[1] = 8'h4C; // L lcd_buffer[2] = 8'h4A; // J lcd_buffer[3] = 8'h55; // U lcd_buffer[4] = 8'h2C; // , lcd_buffer[5] = 8'h20; // 空格 lcd_buffer[6] = 8'h49; // I lcd_buffer[7] = 8'h20; // 空格 lcd_buffer[8] = 8'h4C; // L lcd_buffer[9] = 8'h4F; // O lcd_buffer[10] = 8'h56; // V lcd_buffer[11] = 8'h45; // E lcd_buffer[12] = 8'h20; // 空格 lcd_buffer[13] = 8'h55; // U lcd_buffer[14] = 8'h21; // ! end // 计时器模块 reg [23:0] counter; always @(posedge clk) begin if (!rst_n) begin counter <= 0; end else begin counter <= counter + 1; end end // 使能信号生成模块 reg [1:0] enable_cnt; always @(posedge clk) begin if (!rst_n) begin enable_cnt <= 0; enable <= 0; end else begin case (enable_cnt) 0: begin enable <= 1; lcd_data <= {rs, rw, lcd_buffer[addr]}; end 1: begin enable <= 0; lcd_data <= 16'h0000; end 15: begin enable_cnt <= 0; addr <= (addr == 31) ? 0 : (addr + 1); write_enable <= 1; end default: begin enable <= 0; lcd_data <= 16'h0000; end endcase enable_cnt <= enable_cnt + 1; end end // 数据写入模块 always @(posedge clk) begin if (!rst_n) begin write_enable <= 0; end else begin if (write_enable) begin lcd_buffer[addr] <= data; end write_enable <= 0; end end endmodule ``` 上面的代码中,使用一个计时器模块来产生一个时钟信号,计时器的计数频率是时钟信号的频率的16倍。然后使用一个使能信号生成模块来生成LCD1602的使能信号和数据。在这个模块中,使用一个计数器来计数,根据计数器的值来产生使能信号和数据。最后,使用一个数据写入模块来将数据写入到LCD1602的缓冲区中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值