2014ACM/ICPC亚洲区广州站 北大命题
http://acm.hdu.edu.cn/showproblem.php?pid=5131
现场赛第一个题,水题。题意:给水浒英雄排序,按照杀人数大到小,相同按照名字字典序小到大。输出。然后对每个查询的名字,计数有多少人杀人数大于他,输出个数加1,计数有多少人杀人数相同,但名字小,如果没有不输出,否则输出个数加1。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 struct G{ 6 string name; 7 int kill; 8 friend bool operator <(const G a,const G b){ 9 return a.kill>b.kill||(a.kill==b.kill&&a.name<b.name); 10 } 11 }g[512]; 12 string str; 13 int main(){ 14 int n,m,id; 15 while(~scanf("%d",&n),n){ 16 for(int i=0;i<n;i++){ 17 cin>>g[i].name>>g[i].kill; 18 } 19 sort(g,g+n); 20 for(int i=0;i<n;i++){ 21 cout<<g[i].name<<" "<<g[i].kill<<endl; 22 } 23 scanf("%d",&m); 24 while(m--){ 25 cin>>str; 26 for(int i=0;i<n;i++){ 27 if(str==g[i].name){ 28 id=i; 29 break; 30 } 31 } 32 int ansa=1,ansb=1; 33 for(int i=0;i<id;i++){ 34 if(g[i].kill>g[id].kill){ 35 ansa++; 36 } 37 else{ 38 ansb++; 39 } 40 } 41 printf("%d",ansa); 42 if(ansb>1){ 43 printf(" %d",ansb); 44 } 45 puts(""); 46 } 47 } 48 return 0; 49 }
http://acm.hdu.edu.cn/showproblem.php?pid=5137
第二题,最短路。题意:给一个n点m边带权无向图,可以破坏2到n-1号中任意一个,问破坏哪个后1到n的最短路最长。做法:枚举破坏的点,对于每个最短路,求最大值。
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #define mt(a,b) memset(a,b,sizeof(a)) 5 using namespace std; 6 const int inf=0x3f3f3f3f; 7 bool can[64]; 8 class Spfa { ///单源最短路o(2*ME) 9 typedef int typec;///边权的类型 10 static const int ME=2010;///边的个数 11 static const int MV=64;///点的个数 12 struct E { 13 int v,next; 14 typec w; 15 } e[ME]; 16 int n,le,head[MV],inque[MV]; 17 typec dist[MV]; 18 bool used[MV]; 19 queue<int> q; 20 public: 21 void init(int tn) { ///传入点的个数 22 n=tn; 23 le=0; 24 mt(head,-1); 25 } 26 void add(int u,int v,typec w) { 27 e[le].v=v; 28 e[le].w=w; 29 e[le].next=head[u]; 30 head[u]=le++; 31 } 32 bool solve(int s) { ///传入起点,下标0开始,存在负环返回false 33 for(int i=0; i<=n; i++) { 34 dist[i]=inf; 35 used[i]=true; 36 inque[i]=0; 37 } 38 used[s]=false; 39 dist[s]=0; 40 inque[s]++; 41 while(!q.empty()) q.pop(); 42 q.push(s); 43 while(!q.empty()) { 44 int u=q.front(); 45 q.pop(); 46 used[u]=true; 47 for(int i=head[u]; ~i; i=e[i].next) { 48 int v=e[i].v; 49 if(can[v]) continue; 50 if(dist[v]>dist[u]+e[i].w) { 51 dist[v]=dist[u]+e[i].w; 52 if(used[v]) { 53 used[v]=false; 54 q.push(v); 55 inque[v]++; 56 if(inque[v]>n) return false; 57 } 58 } 59 } 60 } 61 return true; 62 } 63 typec getdist(int id) { 64 return dist[id]; 65 } 66 } g; 67 int main(){ 68 int n,m,u,v,w; 69 while(~scanf("%d%d",&n,&m),n|m){ 70 g.init(n); 71 while(m--){ 72 scanf("%d%d%d",&u,&v,&w); 73 g.add(u,v,w); 74 g.add(v,u,w); 75 } 76 int ans=0; 77 for(int i=2;i<n;i++){ 78 mt(can,0); 79 can[i]=true; 80 g.solve(1); 81 ans=max(ans,g.getdist(n)); 82 } 83 if(ans==inf){ 84 puts("Inf"); 85 continue; 86 } 87 printf("%d\n",ans); 88 } 89 return 0; 90 }
http://acm.hdu.edu.cn/showproblem.php?pid=5135
第三题,bfs。题意:给n个棒子的长度,可以任意挑3个一组组成三角形,不一定要全用完,问最后三角形之和最大是多少。做法:用二进制表示是否用过某个棒子,然后bfs。
bfs,有vis剪了一些情况40ms,vis去掉和下面dfs一样了
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<queue> 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 double area_triangle(double a,double b,double c) {//计算三角形面积,输入三边长 8 double s=(a+b+c)/2; 9 return sqrt(s*(s-a)*(s-b)*(s-c)); 10 } 11 double len[16],ans; 12 bool vis[1<<12][1<<12]; 13 int n; 14 struct Q{ 15 int sta; 16 double area; 17 }now,pre; 18 queue<Q> q; 19 bool judge(double x,double y,double z){ 20 return x+y>z&&x+z>y&&y+z>x; 21 } 22 void bfs(){ 23 mt(vis,0); 24 now.sta=0; 25 now.area=0; 26 while(!q.empty()) q.pop(); 27 q.push(now); 28 while(!q.empty()){ 29 pre=q.front(); 30 q.pop(); 31 ans=max(ans,pre.area); 32 for(int i=0;i<n;i++){ 33 if((pre.sta>>i)&1) continue; 34 for(int j=i+1;j<n;j++){ 35 if((pre.sta>>j)&1) continue; 36 for(int k=j+1;k<n;k++){ 37 if((pre.sta>>k)&1) continue; 38 if(!judge(len[i],len[j],len[k])) continue; 39 now.sta=pre.sta|(1<<i)|(1<<j)|(1<<k); 40 if(vis[pre.sta][now.sta]) continue; 41 vis[pre.sta][now.sta]=true; 42 now.area=pre.area+area_triangle(len[i],len[j],len[k]); 43 q.push(now); 44 } 45 } 46 } 47 } 48 } 49 int main(){ 50 while(~scanf("%d",&n),n){ 51 for(int i=0;i<n;i++){ 52 scanf("%lf",&len[i]); 53 } 54 ans=0; 55 bfs(); 56 printf("%.2f\n",ans); 57 } 58 return 0; 59 }
dfs暴力所有情况171ms
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 #define mt(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 const int M=16; 8 int a[M],n; 9 bool use[M]; 10 double ans; 11 bool judge(int x,int y,int z){ 12 return x+y>z; 13 } 14 double area_triangle(double a,double b,double c) {//计算三角形面积,输入三边长 15 double s=(a+b+c)/2; 16 return sqrt(s*(s-a)*(s-b)*(s-c)); 17 } 18 void dfs(double sum){ 19 ans=max(ans,sum); 20 for(int i=0;i<n;i++){ 21 if(use[i]) continue; 22 for(int j=i+1;j<n;j++){ 23 if(use[j]) continue; 24 for(int k=j+1;k<n;k++){ 25 if(use[k]) continue; 26 if(!judge(a[i],a[j],a[k])) continue; 27 use[i]=use[j]=use[k]=true; 28 dfs(sum+area_triangle(a[i],a[j],a[k])); 29 use[i]=use[j]=use[k]=false; 30 } 31 } 32 } 33 } 34 int main(){ 35 while(~scanf("%d",&n),n){ 36 for(int i=0;i<n;i++){ 37 scanf("%d",&a[i]); 38 } 39 sort(a,a+n); 40 mt(use,0); 41 ans=0; 42 dfs(0); 43 printf("%.2f\n",ans); 44 } 45 return 0; 46 }
状态压缩dp,非常厉害15ms
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 #include<vector> 6 #define mt(a,b) memset(a,b,sizeof(a)) 7 using namespace std; 8 const int M=16; 9 int a[M],n; 10 double dp[1<<12]; 11 vector<int> v; 12 bool judge(int x,int y,int z){ 13 return x+y>z; 14 } 15 double area_triangle(double a,double b,double c) {//计算三角形面积,输入三边长 16 double s=(a+b+c)/2; 17 return sqrt(s*(s-a)*(s-b)*(s-c)); 18 } 19 int main(){ 20 while(~scanf("%d",&n),n){ 21 for(int i=0;i<n;i++){ 22 scanf("%d",&a[i]); 23 } 24 sort(a,a+n); 25 mt(dp,0); 26 int big=1<<n; 27 for(int i=0;i<n;i++){ 28 for(int j=i+1;j<n;j++){ 29 for(int k=j+1;k<n;k++){ 30 if(!judge(a[i],a[j],a[k])) continue; 31 int sta=(1<<i)|(1<<j)|(1<<k); 32 dp[sta]=area_triangle(a[i],a[j],a[k]); 33 v.push_back(sta); 34 } 35 } 36 } 37 int lv=v.size(); 38 for(int i=0;i<big;i++){ 39 for(int j=0;j<lv;j++){ 40 if(i&v[j]) continue; 41 int next=i|v[j]; 42 dp[next]=max(dp[next],dp[i]+dp[v[j]]); 43 } 44 } 45 printf("%.2f\n",dp[big-1]); 46 } 47 return 0; 48 }
http://acm.hdu.edu.cn/showproblem.php?pid=5128
第四题,枚举。题意:给n个点,任意挑8个点构成两个不相交矩形,问能得到最大面积。做法:先处理出所有矩形,然后n^2枚举出两个矩形,如果一个矩形完全在另一个内,边不相交,那面积就是大的矩形的面积,如果相交了那是不合法的,否则就是两个矩形面积和,最后求个面积最大值。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #define mt(a,b) memset(a,b,sizeof(a)) 5 using namespace std; 6 struct point{ 7 int x,y; 8 }p[32]; 9 struct G{ 10 int sx,sy,bx,by; 11 }now; 12 vector<G> g; 13 bool inside(G a,G b){ 14 return a.sx>b.sx&&a.sy>b.sy&&a.bx<b.bx&&a.by<b.by; 15 } 16 int area(G a){ 17 return (a.bx-a.sx)*(a.by-a.sy); 18 } 19 bool in(int x,int y,G b){ 20 return x>=b.sx&&y>=b.sy&&x<=b.bx&&y<=b.by; 21 } 22 bool judge(G a,G b){ 23 return in(a.sx,a.sy,b)||in(a.sx,a.by,b)||in(a.bx,a.sy,b)||in(a.bx,a.by,b); 24 } 25 bool vis[210][210]; 26 int main(){ 27 int n; 28 while(~scanf("%d",&n),n){ 29 mt(vis,0); 30 for(int i=0;i<n;i++){ 31 scanf("%d%d",&p[i].x,&p[i].y); 32 vis[p[i].x][p[i].y]=true; 33 } 34 g.clear(); 35 for(int i=0;i<n;i++){ 36 for(int j=0;j<n;j++){ 37 if(p[i].x<p[j].x&&p[i].y<p[j].y){ 38 if(!vis[p[i].x][p[j].y]) continue; 39 if(!vis[p[j].x][p[i].y]) continue; 40 now.sx=p[i].x; 41 now.sy=p[i].y; 42 now.bx=p[j].x; 43 now.by=p[j].y; 44 g.push_back(now); 45 } 46 } 47 } 48 int lg=g.size(); 49 int ans=0; 50 for(int i=0;i<lg;i++){ 51 for(int j=i+1;j<lg;j++){ 52 if(inside(g[i],g[j])||inside(g[j],g[i])){ 53 ans=max(ans,max(area(g[i]),area(g[j]))); 54 continue; 55 } 56 if(judge(g[i],g[j])||judge(g[j],g[i])) continue; 57 ans=max(ans,area(g[i])+area(g[j])); 58 } 59 } 60 if(!ans){ 61 puts("imp"); 62 continue; 63 } 64 printf("%d\n",ans); 65 } 66 return 0; 67 }
A
题目:1 x y加入x,y ; -1 x y删去 x,y ; 0 a b 查询之前加入的x*a+y*b最大值
暴力n2能过,标程比暴力还慢。。
1 #include<cstdio> 2 typedef long long LL; 3 const int M=5e4+10; 4 struct G{ 5 LL x,y; 6 bool flag; 7 }q[M]; 8 int main(){ 9 int n,a; 10 LL b,c; 11 while(~scanf("%d",&n),n){ 12 int lq=0; 13 while(n--){ 14 scanf("%d%lld%lld",&a,&b,&c); 15 if(a==1){ 16 q[lq].x=b; 17 q[lq].y=c; 18 q[lq].flag=true; 19 lq++; 20 continue; 21 } 22 if(a==-1){ 23 for(int i=0;i<lq;i++){ 24 if(!q[i].flag) continue; 25 if(q[i].x==b&&q[i].y==c){ 26 q[i].flag=false; 27 break; 28 } 29 } 30 continue; 31 } 32 LL ans=-4e18,tmp; 33 for(int i=0;i<lq;i++){ 34 if(!q[i].flag) continue; 35 tmp=q[i].x*b+q[i].y*c; 36 if(ans<tmp){ 37 ans=tmp; 38 } 39 } 40 printf("%lld\n",ans); 41 } 42 } 43 return 0; 44 }
end