简单来说就是完了
思路都对了
就是写不出来
浪费了三个小时来做第一题
还是没有过
然而第三题也没有做对
第二题没空做
这样就...
报零了!
然后第一题:
1.分糖果
(candy.pas/c/cpp)
【问题描述】
幼儿园的小朋友要吃糖果,正在幼儿园帮忙的小x接到了这个任务,当然,这个任务不是那么简单。
现在有n名小朋友,m颗糖果,每个小朋友对糖果的需求都不一样,如果知道第i个小朋友需要x[i]颗糖,但是小x必须分给第i个小朋友y[i]颗糖,老师就认为小朋友的不高兴指数为|x[i]/v-y[i]/m|,那么小x的任务就是要保证所有的小朋友不高兴指数最小,也就是要保证
Σ|x[i]/v – y[i]/m| 最小。这里的Σ是求和,||是绝对值。
现在已知n,m,还知道v=Σx[i]。求分配糖果的方案
【输入】
题目包含多组数据,第一行一个整数K,表示K组测试数据
每组测试数据分为两行,第一行三个整数n,m,v
接下来n个整数,第i个数为x[i]。保证数据合法
【输出】
K行,每行输出对应的n个整数,第i个数位所求的y[i]。
如果有多组解,你只需输出符合条件的一组即可,有special judge。
【输入输出样例1】
candy.in |
candy.out |
1 3 10 4 1 1 2 |
2 3 5 |
【数据范围】
30%的数据中, n、m ≤ 100
100%的数据中,K ≤ 10, n ≤ 100000
m、v ≤ 10^9, 1 ≤ x[i] ≤ 10000
这里给出一个很厉害的P大神的代码
var k,ki,n,m,v,i,me,abme,fme,j,min,dlti,mink,kx:longint;
x,y,dmink,delta,b:array[1..100000]of longint;
yi0R:double;
procedure asson;
begin
assign(input,‘candy.in‘); reset(input);
assign(output,‘candy.out‘); rewrite(output);
end;
procedure assoff;
begin
close(input); close(output);
end;
procedure sort(l,r:longint);
var i,j,mid,temp:longint;
begin
i:=l; j:=r; mid:=delta[(l+r) div 2];
repeat
while (delta[i]<mid) do inc(i);
while (mid<delta[j]) do dec(j);
if (i<=j) then
begin
temp:=delta[i]; delta[i]:=delta[j]; delta[j]:=temp;
temp:=dmink[i]; dmink[i]:=dmink[j]; dmink[j]:=temp;
temp:=b[i]; b[i]:=b[j]; b[j]:=temp;
inc(i); dec(j);
end;
until i>j;
if (l<j) then sort(l,j);
if (i<r) then sort(i,r);
end;
begin
asson;
read(k);
for ki:=1 to k do
begin
read(n,m,v);
for i:=1 to n do read(x[i]);
me:=m;
for i:=1 to n do
begin
yi0R:=x[i]*m/v;
y[i]:=trunc(yi0R);
me:=me-y[i];
end;
while (me<>0) do
begin
abme:=abs(me);
fme:=me div abme;
for i:=1 to n do
begin
min:=maxlongint;
for j:=1 to abme do
begin
if (y[i]+j*fme<0) then break;
dlti:=abs(m*x[i]-v*(y[i]+j*fme))-abs(m*x[i]-v*y[i]);
if (dlti<min) then
begin
min:=dlti;
mink:=j*fme;
end
else break;
end;
delta[i]:=min;
dmink[i]:=mink;
b[i]:=i;
end;
sort(1,n);
for i:=1 to n do
if (me<>0){and(y[b[i]]>0)} then
begin
if (abs(me)>abs(dmink[b[i]])) then kx:=dmink[b[i]]
else kx:=me;
y[b[i]]:=y[b[i]]+kx;
me:=me-kx;
end
else if (me=0) then break;
end;
for i:=1 to n do write(y[i],‘ ‘);
writeln;
end;
assoff;
end.
惨惨的C++:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#Include<string>
using namespace std;
int K,n,m,v,la[10001],jl[],t[10001],x[100001];
int panding(int j){
int u=((la[x[j]])/(t[x[j]]*v));
if(u*v*t[x[j]]>=la[x[j]]){
return u;
}
else{
return u+1;
}
}
int chuli(int maxx){
int laxr=0;
for(int i=1;(i<=maxx)&&(t[i]!=0);i++){
int u=la[i]/(t[i]*v);
char p=u+‘0‘;
int chan=1,mc=0,jh=true;
for(int nowc=la[i]-(u*t[i]*v);jh!=false;){
jh=false;
mc=(t[i]-chan)*u*v+(chan)*(u+1)*v;
if(mc<=nowc){
jh=true;
nowc=mc;
chan++;
}
}
}
}
int main(){
scanf("%d",&K);
for(int i=1;i<=K;i++){
int maxx=0;
scanf("%d %d %d",&n,&m,&v);
for(int j=1;j<=n;j++){
scanf("%d",&x[j]);
maxx=max(maxx,x[j]);
t[x[j]]++;
}
for(int j=1;j<=maxx;j++)
la[j]=j*t[j]*m;
/* for(int j=1;j<=n;j++){
// int gh=(t[x[j]]>1)?((la[x[j]]/(t[x[j]]*v))+1):(((la[x[j]]/v)));
int gh=(panding(j));
cout<<gh<<" ";
la[x[j]]-=gh*(t[x[j]]--)*v;
la[x[j]]=(la[x[j]]>=0)?la[x[j]]:(-la[x[j]]);
}*/
chuli(maxx);
cout<<endl;
}
return 0;
}
然后是第二题:
没时间做啊
题目是这样的:
2.文艺诗人
(poet.pas/c/cpp)
【问题描述】
写诗是每个文艺青年必须要有的技能,小x也不例外。
小x收集到了很多诗句,并且按照平仄韵律排好相应的顺序,根据经验,他可以在这些诗句中连续一些句子组成自己想要的诗,当然,他可以组成很多很多诗。
每个诗句都有两个属性,长度和文艺值,现在小x有n个诗句可以挑选来组诗。一首诗的长度就是组成这首诗的每个句子的长度之和,一首诗的文艺值也是每个句子的文艺值之和。
为了保证组成的诗的整体性和美观性,小x对组诗有以下要求:
1) 挑选诗句必须按照给定的先后顺序挑选,不能调换顺序,同一首诗,必须要在诗句中连续的挑选,数量不限。
2) 一首诗的总长度不能低于一个值low,也不能超过一个值high。诗的总长度是每个诗句的长度之和。
3) 不允许出现两首诗,一首诗所有的语句出现在另一首诗中,也就是说不能出现两首诗是包含与被包含关系。
4) 一个句子可以出现在多首诗中。
现在小x想知道,在满足以上条件的基础上,可以组成的所有诗的最大文艺值是多少
【输入】
第一行,三个整数n,low,high
第二行有N个整数,第i个整数l[i]表示第i句诗句的长度值
第三行有N个整数,第i个整数w[i]表示第i句诗句的文艺值。
【输出】
一个整数S,表示所求的组成所有诗的最大文艺值
【输入输出样例1】
poet.in |
poet.out |
6 4 5 1 3 3 2 2 1 2 3 1 4 5 2 |
21 |
[1,2]的文艺值为5 [3,4]的文艺值为5 [4,6]的文艺值为11 合计文艺值为21
【数据范围】
对于40%的数据,1 <= n <= 100;
对于100%的数据,1 <=n <= 1000;
单个句子的长度和文艺值都小等于100000;
其余给出的均在int范围内。
代码嘛,没有没有
第三题:
3.唯一生成树
(tree.pas/c/cpp)
【问题描述】
小x对生成树很有研究,他很早就发现,一个图的最小生成树并不是唯一的,有一道题目是求次小生成树,当然小x不会让你求。
小x首先画了一颗树,并且他认为这就是某个图的最小生成树,现在他要将这颗树里再加入其它的边,将这个树补成一个完全图,但是要让这颗生成树是这个完全图的唯一最小生成树。
当然,随便的加边肯定可以完成,小x想知道保证最小生成树的基础上,使得补好的完全图的权值累加和最小。
现在小x把问题交给了你,如果能把这个问题解决,你今年的rp会得到很大的增强。
【输入】
此题有多组数据,第一行一个整数M,表示有M组数据。
每组数据第一行一个整数n,表示这颗树有那个节点
接下来有n-1行,每行3个整数 u,v,w,表示点u和点v之间有一条权值为w的边。
【输出】
M行,每行一个整数,表示构成完全图的权值之和。
【输入输出样例1】
tree.in |
tree.out |
1 3 1 2 4 2 3 7 |
19 |
【数据范围】
30%的数据中, n ≤ 1000
100%的数据中,M≤ 20, 1 ≤ n ≤ 15000
1 ≤ u、v ≤ n, w ≤ 10000
保证数据合法
代码嘛:
不太完美的一个C++
还请各位大神完善一下
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<string>
using namespace std;
int m,n,zx=-1,MST=0;
void zse()
{
cin>>n;
int a[n+1][n+1];
bool chao[n+1];
int zxxxx[n+1];
chao[1]=1;
memset(chao,0,sizeof(chao));
memset(a,-1,sizeof(a));
memset(zxxxx,99999999,sizeof(zxxxx));
for(int i=1;i<=n-1;i++)
{
a[i][i]=99999999;
int ll,rr,ee;
cin>>ll>>rr>>ee;
a[ll][rr]=a[rr][ll]=ee;
}
zxxxx[1]=0;
a[n][n]=99999999;
for(int i=1;i<=n;i++)
{
if(a[1][i]!=-1)
{
zxxxx[i]=a[1][i];
}
else
{
zxxxx[i]=99999999;
}
}//潮吧!把数据挪移
for(int i=1;i<=n;i++)
{
int k=0;
zxxxx[0]=99999999;
for(int qwe=1;qwe<=n;qwe++)
if(!chao[qwe]&&(zxxxx[qwe]<zxxxx[k]))
k=qwe;
chao[k]=1;
for(int qwe=2;qwe<=n;qwe++)
if(!chao[qwe]&&a[k][qwe]<zxxxx[qwe])
zxxxx[qwe]=a[k][qwe];
}
for(int i=2;i<=n;i++)
{
MST+=zxxxx[i];
if(zxxxx[i]>zx)
zx=zxxxx[i];
}
zx=zx+1;
int ask=0;
for(int qwe=1;qwe<=n;qwe++)
for(int i=1;i<=n;i++)
if(a[i][qwe]==-1)
ask++;//bulianjiedediandegeshu
ask=ask/2;
MST+=ask*zx;
cout<<MST;
return;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
cin>>m;
for(int i=1;i<=m;i++)
zse();
return 0;
}