特长生模拟——20180421模拟赛

326 篇文章 0 订阅
206 篇文章 0 订阅

已经无话可说了。。。
仔细检查了那么多遍程序,
结果…
估分:100+100+100+100=400
实际:100+100+0+100=300
第三题,很迷,
这里写图片描述
这里写图片描述
这里写图片描述
突然的肝疼…
一开始我打完T3以后发现保存程序名sbest是错的,
然后我改成了subest??…
不多说了,下次努力,争取打破这个魔咒吧..

T1,字符串编辑,题目大意:

给定N个规则以及一篇文章S,每个规则包括一个ai,一个bi,
从第一个规则开始,将S的ai换成bi,直到S中ai不存在,再继续执行下一个规则。

S,所有的ai,bi长度均不超过80个字符
1<=n<=10

题解:

字符串对C++很不友好,用pascal然后枚举一下既可以了。

代码:

var
     a,b:Array [0..105] of string;
     i,j,n,m:longint;
     s,t,w:string;
begin
     assign(input,'editing.in'); reset(input);
     assign(output,'editing.out'); rewrite(output);
     readln(n);
     for i:=1 to n do
         begin
              readln(a[i]);
              readln(b[i]);
         end;
     readln(s);
     i:=1;
     while (i<=n) do
           begin
                 j:=pos(a[i],s);
                 while (j<>0) do
                       begin
                             delete(s,j,length(a[i]));
                             insert(b[i],s,j);
                             j:=pos(a[i],s);
                       end;
                 inc(i);
           end;
     while (s[length(s)]=' ') do delete(s,length(s),1);
     writeln(s);
     close(input); close(output);
end.

T2,糊涂的教授,题目大意:

有n张幻灯片,它们按照演讲要使用的顺序已经用数字1,2,…,n 编号。因为幻灯片是透明的,所以我们不能一下子看清每一个数字所对应的幻灯片。
现在我们用大写字母 A,B,C,…,再次把幻灯片依次编上号。
给出N张幻灯片的xmin_i,xmax_i,ymin_i,ymax_i,以及N个数字的xi,yi。
求幻灯片的数字编号和字母编号对应起来的方式。
显然这种对应应该是唯一的;
若是出现多种对应的情况或是某些数字编号和字母对应不起来,我们就称对应是无法实现的,输出None。

n<=26

题解:

因为答案要求满足唯一性,
所以我们可以知道,
如果存在可行解,则
一开始必然存在一个点仅仅被一个幻灯片覆盖,
然后我们将这个点以及它所对应的幻灯片去掉,
则下一次必定也存在一个点仅仅被一个幻灯片覆盖,
so模拟即可,
如果某一时刻并没有将所有的点跟幻灯片匹配完,且所有的点都至少存在2个幻灯片覆盖其上,则可以发现是无解的。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define N 105

using namespace std;

struct node{
    int x1,y1,x2,y2;
}a[N];

int ans[N],x[N],y[N],n;
bool c[N],d[N];

int main()
{
    freopen("jiaoshou.in","r",stdin);
    freopen("jiaoshou.out","w",stdout);
    scanf("%d",&n);
    for (int i=1; i<=n; i++)
         scanf("%d%d%d%d",&a[i].x1,&a[i].x2,&a[i].y1,&a[i].y2);
    for (int i=1; i<=n; i++)
         scanf("%d%d",&x[i],&y[i]);
    int check=1;
    while (check){
           check=0;
           for (int i=1; i<=n; i++)
                if (!c[i]){
                    int rp=0,cp=0;
                    for (int j=1; j<=n; j++) 
                         if (!d[j] && x[i]>=a[j].x1 && x[i]<=a[j].x2 && 
                                      y[i]>=a[j].y1 && y[i]<=a[j].y2) rp++,cp=j;
                    if (rp==1) {
                        c[i]=1;
                        d[cp]=1;
                        ans[cp]=i; 
                        check=1;
                    }
                    if (check) break;
                }
            if (!check) break;
    }
    check=1;
    for (int i=1; i<=n; i++)
         if (!ans[i]) check=0;
    if (check) {
         for (int i=1; i<=n; i++)
         {
              char ch='A'+i-1;
              cout<<ch<<' '<<ans[i]<<endl;
         }
    } else printf("None");
    return 0;
}

T3,集合问题,题目大意:

对于从1到N的连续整数集合,能划分成两个子集合,且保证每个集合的数字和是相等的。
给出 N,你的程序应该输出划分方案总数,如果不存在这样的划分方案,则输出 0。程序不能预存结果直接输出。

1<=N<=39

题解:

我们可以发现,
设m=∑n
如果要满足划分,
首先先要满足m是2的倍数,
因为要分成等量的2部分,
然后我们
设p=m/2
设f[i][j]表示考虑了1~i以后总和为j的子集合有多少个,
则可以i枚举1~n,然后j枚举1~p
f[i][j]=f[i][j]+f[i-1][j-i]
然后压一下维度,就是我下面这个了。
因为交换集合位置被认为是同一种划分方案,
所以最后的ans要/2

代码:

#include<algorithm>
#include<iostream>
#include<cstdio>
#define N 1005

using namespace std;

long long f[N];
int n,m;

int main()
{
    freopen("subset.in","r",stdin);
    freopen("subset.out","w",stdout);
    scanf("%d",&n);
    m=(n+1)*n/2;
    if (m%2==0){
        m=m/2;
        f[0]=1;
        for (int i=1; i<=n; i++)
             for (int j=m; j>=i; j--) f[j]+=f[j-i];
        printf("%d\n",f[m]/2);
    } else printf("0\n");
    return 0;
}

T4,书本整理,题目大意:

书架上有N本书,要求将所有书按高度hi从小到大排列,并且每本书有一个宽度wi,这个凌乱值定义为相邻两本书的宽度差的绝对值的和。
拿掉其中的k本书,使凌乱值最小,问最小值为多少。

已知每本书的高度都不一样。
30%的数据, n<=20。
100%的数据, n<=100,k < n。

题解:

∵拿掉k本书
∴显然,最后剩下了n-k本书
∴排序一下,
然后我们设f[i][j]表示前i本书选了j本书留下来且第j本为i的时候的最小值
则我们要从前j-1~i-1本书中选j-1本书
则可以推出,f[i][j]=min(f[k][j-1]+abs(w[i]-w[k]))
注意一下f[i][1]的时候因为只有一本书,
所以是为0的,其他的f[i][j]初值都设一个极大的值即可

#include<algorithm>
#include<iostream>
#include<cstdio>
#define INF 2333333
#define N 105

using namespace std;

int h[N],w[N],f[N][N],n,m;

int num(int aa,int bb){
    if (aa>bb) return aa-bb;
    return bb-aa;
}

int main()
{
    freopen("book.in","r",stdin);
    freopen("book.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++) scanf("%d%d",&h[i],&w[i]);
    for (int i=1; i<n; i++)
         for (int j=i+1; j<=n; j++)
              if (h[i]>h[j]){
                  h[0]=h[i];h[i]=h[j];h[j]=h[0];
                  w[0]=w[i];w[i]=w[j];w[j]=w[0];
              } 
    for (int i=2; i<=n; i++)
         for (int j=2; j<=i; j++) f[i][j]=INF;
    for (int i=2; i<=n; i++)
         for (int j=2; j<=i; j++)
              for (int k=j-1; k<=i-1; k++) 
                   f[i][j]=min(f[i][j],f[k][j-1]+num(w[i],w[k]));
    int ans=INF;
    for (int i=n-m; i<=n; i++) ans=min(ans,f[i][n-m]);
    printf("%d\n",ans);
    return 0;   
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值