哈尔滨理工大学第七届程序设计竞赛初赛(高年级组)

https://www.nowcoder.com/acm/contest/27#question

   A-凌波微步

  LIS恐成最大输家,无力吐槽 = =

B-C水题

D-经商

小d是一个搞房地产的土豪。每个人经商都有每个人经商的手段,当然人际关系是需要放在首位的。

小d每一个月都需要列出来一个人际关系表,表示他们搞房地产的人的一个人际关系网,但是他的精力有限,对应他只能和能够接触到的人交际。比如1认识2,2认识3,那么1就可以接触3进行交际,当然1和2也可以交际。

小d还很精明,他知道他和谁交际的深获得的利益大,接下来他根据自己的想法又列出来一个利益表,表示他和这些人交际需要耗用多少精力,能够获得的利益值为多少。

小d想知道,他在精力范围内,能够获得的利益值到底是多少。

设定小d自己的编号为1.并且对应一个人的交际次数限定为1.

输入描述:

本题包含多组输入,第一行输入一个数t,表示测试数据的组数
每组数据的第一行输入三个数,N,M,C,表示这个人际关系网一共有多少个人,关系网的关系数,以及小d的精力值
接下来N-1行,每行两个数ai,bi。这里第i行表示和编号为i+1的人认识需要花费ai的精力,能够获得的利益值为bi。
再接下来M行,每行两个数x,y,表示编号为x的人能够和编号为y的人接触
t<=50
2<=N<=10000
1<=M<=10*N
1<=ai,bi<=10
1<=C<=500
1<=x,y<=N

输出描述:

输出包含一行,表示小d能够获得的最大利益值
示例1

输入

1
5 3 7
5 10
3 2
4 3
1 100
1 2
2 3
1 4

输出

10
并查集统计出1所有能接触到的人+背包求解最优值
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int f[10005],dp[550];
 4 int getf(int v){return f[v]==v?v:f[v]=getf(f[v]);}
 5 struct node
 6 {
 7     int a,b;
 8 }P[10005],Q[10005];
 9 int main()
10 {
11     int T,N,M,C,i,j,k,x,y;
12     scanf("%d",&T);
13     while(T--){int sq=0;
14     memset(dp,0,sizeof(dp));
15         scanf("%d%d%d",&N,&M,&C);
16         for(i=1;i<=N;++i) f[i]=i;
17         for(i=2;i<=N;++i)
18         {
19             scanf("%d%d",&P[i].a,&P[i].b);
20         }
21         for(i=1;i<=M;++i)
22         {
23             scanf("%d%d",&x,&y);
24             int fx=getf(x),fy=getf(y);
25             if(fx!=fy){
26                 f[fx]=fy;
27             }
28         }
29         for( i=1;i<=N;++i) f[i]=getf(i);
30         int root=f[1];
31         for(i=2;i<=N;++i)
32         {
33             if(f[i]==root){
34                 Q[++sq]=P[i];
35             }
36         }
37         for(i=1;i<=sq;++i)
38         {
39             for(j=C;j>=Q[i].a;--j)
40                 dp[j]=max(dp[j],dp[j-Q[i].a]+Q[i].b);
41         }
42         cout<<dp[C]<<endl;
43     }
44     return 0;
45 }

 

F-苦逼的单身狗
尺取法,枚举左边界,指定情况出现时再指定情况未消失时不断右移左边界并统计数量。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char s[100005];
 4 int vis[5];
 5 int zh[30];
 6 #define inf 0x3f3f3f3f
 7 int main()
 8 {
 9     int t,n,m,i,j,k;
10     zh['L']=1;
11     zh['O']=2;
12     zh['V']=3;
13     zh['E']=4;
14     cin>>t;
15     while(t--){
16             cin>>s;
17             memset(vis,0,sizeof(vis));
18     int len=strlen(s);
19     long long ans=0;
20     int cur=0;
21     for(i=0;i<len;++i)
22     {
23        k=zh[s[i]];
24        if(k){
25         vis[k]++;
26        }
27        while(cur<=i&&vis[4]&&vis[1]&&vis[2]&&vis[3]){
28         ans+=(long long )len-i;//cout<<len-i<<endl;
29         if(zh[s[cur]]) vis[zh[s[cur]]]--;
30         cur++;
31        }
32     }
33     printf("%lld\n",ans);
34     }
35     return 0;
36 }

H-布置会场

矩阵幂裸题。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 using namespace std;
 6 #define LL long long
 7 LL M=1000000007;
 8  
 9 struct Matrix {
10     long long a[2][2];
11     Matrix() {
12         memset(a, 0, sizeof(a));
13     }
14     Matrix operator * (const Matrix y) {
15         Matrix ans;
16         for(int i = 0; i <= 1; i++)
17             for(int j = 0; j <= 1; j++)
18                 for(int k = 0; k <= 1; k++)
19                     ans.a[i][j] += a[i][k]*y.a[k][j];
20         for(int i = 0; i <= 1; i++)
21             for(int j = 0; j <= 1; j++)
22                 ans.a[i][j] %= M;
23         return ans;
24     }
25     void operator = (const Matrix b) {
26         for(int i = 0; i <= 1; i++)
27             for(int j = 0; j <= 1; j++)
28                 a[i][j] = b.a[i][j];
29     }
30 };
31  
32 int solve(long long x) {
33     Matrix ans, trs;
34     ans.a[0][0] = ans.a[1][1] = 1;
35     trs.a[0][0] = trs.a[1][0] = trs.a[0][1] = 1;
36     while(x) {
37         if(x&1)
38             ans = ans*trs;
39         trs = trs*trs;
40         x >>= 1;
41     }
42     return ans.a[0][0];
43 }
44  
45 int main() {
46     long long n;
47     int t;
48     cin>>t;
49     while(t--){
50     scanf("%lld", &n);
51     cout << solve(n) << endl;
52     }
53     return 0;
54 }

 

I-旅行
最短路+思维。
题目很显然就是求最大化的{任意有两条最短路连接的三个点中的这两条最短路径长度和},其中三个点互不相等。
首先我们要求出任意两点间的最短路这是肯定的,有N^3的floyd或是N*N*log(N)的dij,前者肯定炸了。对于后面的找这三个点的过程一直想的是N*N*N,这样的话无论最短路算法在再优化也会T,比赛时迫于时间
直接暴力了个floyd直接炸了。
其实找点用不到这么麻烦,题目求得时最大化的,三个点显然只有两条最短路,我们枚举1-n作为中转点,没次找到中转点对于其他点最大的两条最短路更新答案就好了。这样找的复杂度就降到了N^2不会T了。
好题。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define inf 0x3f3f3f3f
 4 struct Edge
 5 {
 6     int to,w,next;
 7 }e[2010];
 8 int first[1010],cnt;
 9 struct node
10 {
11     int u,w;
12     bool operator<(const node& t)const{
13     return w>t.w;
14     }
15 };
16 void add(int u,int v,int w)
17 {
18     e[cnt].to=v;
19     e[cnt].w=w;
20     e[cnt].next=first[u];
21     first[u]=cnt++;
22 }
23 int d[1005][1005];
24 bool vis[1005];
25 void dij(int u,int n)
26 {
27     priority_queue<node>Q;
28     node t1,t2;
29     memset(vis,0,sizeof(vis));
30     d[u][u]=0;
31     Q.push(node{u,0});
32     while(!Q.empty()){
33         t1=Q.top();
34         Q.pop();
35         if(vis[t1.u]) continue;
36         vis[t1.u]=1;
37         for(int i=first[t1.u];i+1;i=e[i].next){
38             if(d[u][e[i].to]>d[u][t1.u]+e[i].w){
39                 d[u][e[i].to]=d[u][t1.u]+e[i].w;
40                 Q.push(node{e[i].to,d[u][e[i].to]});
41             }
42         }
43     }
44 }
45 int main()
46 {
47     int t,n,m,i,j,k,u,v,w;
48     cin>>t;
49     while(t--){
50         cin>>n>>m;
51         memset(first,-1,sizeof(first));
52         memset(d,inf,sizeof(d));
53         cnt=0;
54         for(i=1;i<=m;++i)
55         {
56             scanf("%d%d%d",&u,&v,&w);
57             add(u,v,w);
58             add(v,u,w);
59         }
60         for(i=1;i<=n;++i) dij(i,n);
61         int ans=-1;
62         for(i=1;i<=n;++i)
63         {
64             int t1=-1,t2=-1,maxn=0;
65             for(j=1;j<=n;++j)
66             {
67                 if(d[i][j]!=inf&&d[i][j]>maxn){
68                     maxn=d[i][j];
69                     t1=j;
70                 }
71             }
72             maxn=0;
73             for(j=1;j<=n;++j)
74             {
75                 if(j!=t1&&d[i][j]!=inf&&d[i][j]>maxn){
76                     maxn=d[i][j];
77                     t2=j;
78                 }
79             }
80             if(t1!=-1&&t2!=-1){
81                 ans=max(ans,d[i][t1]+d[i][t2]);
82             }
83         }
84         printf("%d\n",ans);
85     }
86     return 0;
87 }

 



posted @ 2017-12-10 09:36  *zzq  阅读(268)  评论(0编辑  收藏  举报