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 }
View Code

 

 

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 }
View Code

 

 

 

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 }
View Code

 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 }
View Code

 状态压缩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 }
View Code

 

 

 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 }
View Code

 

 

 

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 }
View Code

 

 

 

 

 

end

转载于:https://www.cnblogs.com/gaolzzxin/p/4207083.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值