ACM/ICPC 2014 北京站题 解题报告

A题好福利,哇哈哈

#include<cstdio>
#include<memory>
using namespace std;
int data[1000010];
double dmax(double a,double b){
	return a>b?a:b;
}
int abs(int a){
	return a>0?a:-a;
}
int main(){
	int t,tn,n,i,j;
	double max;
	scanf("%d",&t);
	for(tn=1;tn<=t;tn++){
		scanf("%d",&n);
		memset(data,-1,sizeof(data));
		for(i=1;i<=n;i++){
			scanf("%d",&j);
			scanf("%d",&data[j]);
		}
		j=-1;
		max=-1.0;
		for(i=0;i<=1000010;i++) if(data[i]!=-1){
			if(j!=-1) max=dmax(max,(double)abs(data[i]-data[j])/(double)(i-j));
			j=i;
		}
		printf("Case #%d: %.2lf\n",tn,max);
	}
	return 0;
}

B题 我试着从右上沿对角线填,每填完一种颜色换下一种颜色,填完一半并填完当前颜色以后,剩下的就可以随便填了,5x5以内能AC,数据再大我也没把握,但我觉得这种填法挺有意思的

15ms Accept!!

--------------------------------------

#include<cstdio>
#include<algorithm>
using namespace std;
typedef struct{
	int index;
	int number;
	int used;
}color;
bool cmp(color a,color b){
	return a.number>b.number;
}
color c[26];
int map[6][6],n,m,k,hmax;int nextcolor(int l){
	int i,mmax=0,ncl=0;
	for(i=1;i<=k;i++) if(!c[i].used&&c[i].number<=l&&mmax<c[i].number){
		mmax=c[i].number;
		ncl=i;
	}
	if(ncl==0) for(i=k;i>=1;i--) if(!c[i].used) {ncl=i;break;}
	c[ncl].used=1;
	return ncl;
}
void printmap(){
	int sum,i,j,d,p;
	if(n*m%2==0) j=m-1;
	else j=m;
	d=j>0?0:1;
	p=1;
	c[1].used=1;
	sum=c[1].number;
	for(i=1;i<=hmax;i++){
		map[1+d][j+d]=c[p].index;
		if(--c[p].number==0){
			p=nextcolor(hmax-sum);
			sum+=c[p].number;}
		d++;
		if(j+d>m||1+d>n){
			j-=2;
			d=0;
			while(j+d<1) d++;
		}
	}
	if(n*m%2==0) j=m;
	else j=m-1;
	d=j>0?0:1;
	if(sum!=hmax){
		while(c[p].number){
			map[1+d][j+d]=c[p].index;
			if(--c[p].number==0) break;
			d++;
			if(j+d>m||1+d>n){
				j-=2;
				d=0;
				while(j+d<1) d++;
			}
		}
		p=nextcolor(0);
	}
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			if(!map[i][j]){
				map[i][j]=c[p].index;
				if(--c[p].number==0) p=nextcolor(0);
			}for(i=1;i<=n;i++){
				printf("%d",map[i][1]);
				for(j=2;j<=m;j++) printf(" %d",map[i][j]);
				printf("\n");
			}
			
}
int main(){
	int t,tn,i;
	scanf("%d",&t);
	for(tn=1;tn<=t;tn++){
		scanf("%d %d %d",&n,&m,&k);
		for(i=1;i<=k;i++){
			c[i].index=i;
			c[i].used=0;
			scanf("%d",&c[i].number);
		}
		sort(c+1,c+1+k,cmp);
		hmax=(int)((double)n*m/2.0+0.5);
		printf("Case #%d:\n",tn);
		if(c[1].number>hmax) printf("NO\n");
		else{
			memset(map,0,sizeof(map));
			printf("YES\n");
			printmap();
		}
	}
	return 0;
}		

C题 最小公倍数的题,做完D再回来做

--------------------------------------------

问题并不复杂,常见的运动分解,在x,y轴两个分解运动的公共周期内如果不会碰撞就永远不会碰撞

数据非常大,需要用到64位int,否则计算lcm(2x,2y)会溢出,判断在公共周期内两坐标轴是否会同时碰撞时我采用了二分搜索,187msAC

从开始写到AC花了快1个小时的时间。。。昨天的思考时间无法计算。。。我果然太小看ACM了啊。。。乖乖刷水题去好了

#include<cstdio>

double tx[1000001],ty[1000001];

int gcd(int a,int b){
	if(a%b==0) return b;
	else return gcd(b,a%b);
}

int abs(int a){
	return a>0?a:-a;
}

int max(int a,int b){
	return a>b?a:b;
}

double hilove(int p1,int p2,__int64 l){
	if(p1==p2) return 0;
	return abs(p1-p2)/2.0+l-max(p1,p2);
}
double locate(int s,__int64 l,double t){
	while(t>2*l) t-=2*l;
	if(t<=l-s) return s+t;
	if(t>l-s&&t<=2*l-s) return 2*l-t-s;
	if(t>2*l-s) return t-2*l+s;
}


int binary_search(int l,int r,double t){  
    int mid=(r+l)/2;  
    if(tx[mid]==t) return mid;
	if(mid==l) return 0;
    if(tx[mid]>t) binary_search(l,mid,t);  
    else binary_search(mid,r,t);}



int main(){
	__int64 xyl,xl,yl;
	int t,tn,x1,x2,y1,y2,txl,tyl,i,pos;
	scanf("%d",&t);
	for(tn=1;tn<=t;tn++){
		scanf("%I64d %I64d\n%d %d %d %d",&xl,&yl,&x1,&y1,&x2,&y2);
		xyl=xl/gcd(xl,yl)*yl*2;
		tx[1]=hilove(x1,x2,xl);
		ty[1]=hilove(y1,y2,yl);
		printf("Case #%d:\n",tn);
		if(tx[1]==0&&ty[1]==0){
			printf("%.1lf %.1lf\n",(double)x1,(double)y1);
			continue;
		}
		if(tx[1]==0){
			printf("%.1lf %.1lf\n",locate(x1,xl,ty[1]),locate(y1,yl,ty[1]));
			continue;
		}
		if(ty[1]==0){
			printf("%.1lf %.1lf\n",locate(x1,xl,tx[1]),locate(y1,yl,tx[1]));
			continue;
		}
		for(txl=1;tx[txl]<=xyl;txl++) tx[txl+1]=tx[txl]+xl;
		for(tyl=1;ty[tyl]<=xyl;tyl++) ty[tyl+1]=ty[tyl]+yl;
		for(i=1;i<tyl;i++) if(pos=binary_search(1,txl,ty[i])) break;
		if(!pos) printf("Collision will not happen.\n");
		else printf("%.1lf %.1lf\n",locate(x1,xl,ty[i]),locate(y1,yl,ty[i]));

	}

}

 

 

D题 折腾了挺久的,今天精神不好,睡了3个小时没到,晚上回去一定好好补觉啊魂淡,头等大事就是睡觉啊魂淡!!!有什么事情有这个重要啊魂淡魂淡魂淡!!

#include<cstdio>
#include<memory>
using namespace std;
int dp[202][202];
int vis[202][202];
int eh[202];
int min(int a,int b){
	return a<b?a:b;
}
int main(){
	int t_t,t_tt,n,ah,sum,i,k,d;
	scanf("%d",&t_tt);
	for(t_t=1;t_t<=t_tt;t_t++){
		scanf("%d",&n);
		sum=0;
		for(i=1;i<=n;i++){scanf("%d",&ah);sum+=ah;}
		for(i=1;i<=n;i++) scanf("%d",eh+i);
		eh[0]=eh[n+1]=0;
		memset(dp,0,sizeof(dp));
		memset(vis,0,sizeof(vis));
		for(i=1;i<=n;i++) dp[i][i]=eh[i-1]+eh[i+1];
		for(k=1;k<n;k++)
			for(i=1;i+k<=n;i++)
				for(d=i;d<=i+k;d++){
					if(vis[i][i+k]) dp[i][i+k]=min(dp[i][i+k],dp[i][d-1]+dp[d+1][i+k]+eh[i-1]+eh[i+k+1]);
					else {vis[i][i+k]=1;dp[i][i+k]=dp[i][d-1]+dp[d+1][i+k]+eh[i-1]+eh[i+k+1];}
				}
		printf("Case #%d: %d\n",t_t,sum+dp[1][n]);
	}
}

E题 呐呐呐,我又回来了!

-------------------------

去刷水题了。。。。。。。。
 ------------------------

啦啦啦,我又萌萌哒回来啦,先说下思路,用一个矩阵保存输入的点,每当选定一个L的时候将L涉及的点从矩阵中删去,统计剩余矩阵中的所有L

这样想法是没错的。。。但是超时是肯定哒啦~~

--------------------------

哪位大腿有不TLE的码吗?给人家看看好不好。。。


 K题 签个到,我逛4399去了,\(^o^)/~

#include<cstdio>
int s[3000010];
int main(){
	int tn,tnn,n,i,min,sum;
	scanf("%d",&tnn);
	for(tn=1;tn<=tnn;tn++){
		scanf("%d",&n);
		min=10000000;
		sum=0;
		for(i=1;i<=n;i++) scanf("%d",&s[i]);
		for(i=n;i>=1;i--){
			if(s[i]>min) sum++;
			else min=s[i];
		}
		printf("Case #%d: %d\n",tn,sum);
	}
	return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值