已经无话可说了。。。
仔细检查了那么多遍程序,
结果…
估分: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;
}