2015年江西理工大学C语言程序设计竞赛(高级组)
A
解法:DP+二分
dp[i]=max(dp[i],dp[j]+p[i].v)(i>j)
dp[i]表示建立i点之后能够获得的最大值
int n,M; struct node { int l,v; }p[1010]; int dp[1010]; bool cmp(node a,node b){ return a.l < b.l; } bool judge_oo(){ int Max = -1; for(int i = 1;i <= n;i++) Max = max(Max,p[i].v); if(Max >= M) return 1; return 0; } bool judge_no(){ int sum = 0; for(int i = 1;i <= n;i++) sum += p[i].v; if(sum >= M) return 0; return 1; } bool judge_DP(int L){ memset(dp,0,sizeof dp); for(int i = 1;i <= n;i++){ for(int j = 0;j < i; j++){ if(p[i].l - p[j].l >= L){ dp[i] = max(dp[i],dp[j] + p[i].v); } } } int ML = 0; for(int i = 1;i <= n;i++) ML = max(ML,dp[i]); if(ML >= M) return 1; return 0; } int solve(int L,int R){ while(L + 1 < R){ int mid = (L + R)/2; if(judge_DP(mid)) L = mid; else R = mid; } return L; } int main(int argc, char *argv[]) { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int T; cin >> T; while(T--){ cin >> n >> M; for(int i = 1;i <= n;i ++) cin >> p[i].l >> p[i].v; if(judge_no()){ puts("-1"); continue; } if(judge_oo()){ puts("oo"); continue; } sort(p+1,p+n+1,cmp); p[0].l = -100000000 , p[0].v = 0; int L = 1 , R = p[n].l; cout << solve(L,R) << endl; } return 0; }
B
解法:模拟。字符串模拟
#include<stdio.h>
//#include<bits/stdc++.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<sstream>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#include<limits.h>
#define inf 0x3fffffff
#define INF 0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define ULL unsigned long long
using namespace std;
int i,j;
int n,m;
int num_1,num_2;
int t;
int sum,ans,flag;
string s_1,s_2,s_3;
string sss;
string ss[10000];
string c;
map<string,int>q1;
map<string,int>q2;
int main()
{
cin>>t;
while(t--)
{
cin>>n>>c;
num_1=0;
for(i=0; i<n; i++)
{
cin>>sss;
ans=sss.find(".");
s_1=sss.substr(0,ans);
s_2=sss.substr(ans+1,sss.length());
if(s_2==c)
{
int ans_2=sss.find("(");
int ans_3=sss.find(")");
if((ans_2!=-1&&ans_2<ans_3))
{
// num_1++;
ss[num_1++]=sss.substr(0,ans_2);
// cout<<sss.substr(0,ans_2)<<endl;
}
else if(ans_2==-1||ans_3==-1)
{
// num_1++;
ss[num_1++]=sss.substr(0,ans);
// cout<<sss.substr(0,ans)<<endl;
}
}
}
for(i=0; i<num_1; i++)
{
// cout<<ss[i]<<"A"<<endl;
}
// cout<<num_1<<endl;
for(i=0; i<num_1; i++)
{
q1[ss[i]]++;
}
for(i=0; i<num_1; i++)
{
if(q2[ss[i]]==0)
{
q2[ss[i]]=1;
if(q1[ss[i]]==1)
{
cout<<ss[i]<<"."<<c<<endl;
}
else
{
cout<<ss[i]<<"."<<c<<" "<<q1[ss[i]]<<endl;
}
}
}
q1.clear();
q2.clear();
}
return 0;
}
C
解法:树状数组寻找逆序对+预处理
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> using namespace std; const int M = 200010; long long ans[M + 10]; int G[M + 10],c[M + 10]; int Lowbit(int x) { return x & (-x); } void Insert(int x,int d) { while(x<=M){ c[x]+=d; x+=Lowbit(x); } } int Sum(int x) { int sum=0; while(x>0){ sum+=c[x]; x-=Lowbit(x); } return sum; } void init() { memset(G,-1,sizeof G); memset(ans,0,sizeof ans); memset(c,0,sizeof c); G[1] = 1; for(int i = 2; i <= 200100;i++){ if(G[i] == -1){ for(int j = i;j <= 200100;j += i){ if(G[j] == -1){ G[j] = i; } } } } for(int i=1;i<=200005;i++) { Insert(G[i],1); ans[i] = ans[i-1] + (i-Sum(G[i])); } } int main() { init(); int t; cin>>t; while(t--) { int n; cin>>n; cout<<ans[n]<<endl; } return 0; }
D
解法:模版题,最小覆盖圆
#include<iostream> #include<cmath> #include<cstdio> #include<algorithm> using namespace std; const double eps=1e-8; struct Point{ double x,y; }p[505]; double dis(const Point &a,const Point &b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } Point circumcenter(const Point &a,const Point &b,const Point &c) { //返回三角形的外心 Point ret; double a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)/2; double a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)/2; double d=a1*b2-a2*b1; ret.x=a.x+(c1*b2-c2*b1)/d; ret.y=a.y+(a1*c2-a2*c1)/d; return ret; } void min_cover_circle(Point *p,int n,Point &c,double &r){ //c为圆心,r为半径 random_shuffle(p,p+n); // c=p[0]; r=0; for(int i=1;i<n;i++) { if(dis(p[i],c)>r+eps) //第一个点 { c=p[i]; r=0; for(int j=0;j<i;j++) if(dis(p[j],c)>r+eps) //第二个点 { c.x=(p[i].x+p[j].x)/2; c.y=(p[i].y+p[j].y)/2; r=dis(p[j],c); for(int k=0;k<j;k++) if(dis(p[k],c)>r+eps) //第三个点 {//求外接圆圆心,三点必不共线 c=circumcenter(p[i],p[j],p[k]); r=dis(p[i],c); } } } } } int main(){ int n; Point c; double r; int t; cin>>t; while(t--) { cin>>n; for(int i=0; i<n; i++) scanf("%lf%lf",&p[i].x,&p[i].y); min_cover_circle(p,n,c,r); printf("%.1f %.1f\n",c.x,c.y); } return 0; }

浙公网安备 33010602011771号