0914测试【提高组】(系实验选拔考2)

第一题:



A: 最小比例

时间限制: 1 Sec  内存限制: 128 MB
提交: 55  解决: 13
[提交][状态][讨论版]

题目描述

图中共有N个点的完全图,每条边都有权值,每个点也有权值。要求选出M个点和M-1条边,构成一棵树,使得:



即所有边的权值比所有点的权值之和的比率最小。 
给定N和M,以及N个点的权值,和所有的边权,要求M个点的最小比率生成树。

 

输入

第一行包含两个整数N和M(2<=N<=15,2<=M<=N),表示点数和生成树的点数。 
接下来一行N个整数,表示N个点的边权。 
最后N行,每行N列,表示完全图中的边权。所有点权和边权都在[1,100]之间。

 

输出

输出最小比率生成树的M个点。当答案出现多种时,要求输出的第一个点的编号尽量小,第一个相同,则第二个点的编号尽量小,依次类推,中间用空格分开。编号从1开始。

 

样例输入

3 2
30 20 10
0 6 2
6 0 3
2 3 0

2 2
1 1
0 2
2 0

样例输出

1 3

1 2

提示

 

【样例解释1】




取1,3,号点。


【数据范围】

对于30%数据,N<=5。


 

 

来源

 
这题一看就看到那神奇的15,让人不忍往2^15次的方面考虑,
掐指一算,好像时间还多很多,那还忍什么!!
斌哥大暴力直接上,枚举每个点取不取,
而题目要求值最小,再来次最小生成树就A了!
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<cstdlib>
  7 #include<vector>
  8 using namespace std;
  9 typedef long long ll;
 10 typedef long double ld;
 11 typedef pair<int,int> pr;
 12 const double pi=acos(-1);
 13 #define rep(i,a,n) for(int i=a;i<=n;i++)
 14 #define per(i,n,a) for(int i=n;i>=a;i--)
 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
 16 #define clr(a) memset(a,0,sizeof(a))
 17 #define pb push_back
 18 #define mp make_pair
 19 #define fi first
 20 #define sc second
 21 #define pq priority_queue
 22 #define pqb priority_queue <int, vector<int>, less<int> >
 23 #define pqs priority_queue <int, vector<int>, greater<int> >
 24 #define vec vector
 25 ld eps=1e-9;
 26 ll pp=1000000007;
 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
 29 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
 30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
 31 ll read(){ ll ans=0; char last=' ',ch=getchar();
 32 while(ch<'0' || ch>'9')last=ch,ch=getchar();
 33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
 34 if(last=='-')ans=-ans; return ans;
 35 }
 36 //头文件
 37 
 38 
 39 
 40 
 41 ld Min=1000000;
 42 int n,m,nu,a[20],q[20],fa[20],Ans[20];
 43 struct node{
 44     int x,y,num;
 45 }f[500];
 46 bool cmp(node a,node b){
 47     return a.num<b.num;
 48 }
 49 int getfa(int x){
 50     if(fa[x]!=x) fa[x] = getfa(fa[x]);
 51     return fa[x];
 52 }
 53 int same(int x,int y){
 54     return getfa(x)==getfa(y);
 55 }
 56 void merge(int x,int y)
 57 {
 58     int fax=getfa(x),fay=getfa(y);
 59     fa[fax]=fay;
 60 }
 61 void work()
 62 {
 63     int first=0;
 64     rep(i,1,n) 
 65       if (q[i]) first=i;
 66     rep(i,1,n) fa[i]=i; 
 67     int st=m,ansP=0;
 68     for (int i=1;i<=nu && st>1;i++)
 69     {
 70         int x=f[i].x,y=f[i].y;
 71         if (q[x] && q[y])
 72           {
 73             if(same(x,y)) continue;
 74             else{
 75               merge(x,y);
 76               st--;
 77               ansP+=f[i].num;
 78             }
 79         }
 80     }
 81     int ansW=0;
 82     rep(i,1,n) if (q[i]) ansW+=a[i];
 83     if (Min>((ld)ansP/(ld)ansW)) {
 84         Min=((ld)ansP/(ld)ansW);
 85         rep(i,1,n) Ans[i]=q[i];
 86     } 
 87 }
 88 void dfs(int t)
 89 {
 90     if (t>n){
 91         int number=0;
 92         rep(i,1,n) if (q[i]) number++; 
 93         if (number==m) work(); return;
 94     }
 95     q[t]=1; dfs(t+1);
 96     q[t]=0; dfs(t+1);
 97 }
 98 int main()
 99 {
100     n=read(); m=read(); nu=0;
101     rep(i,1,n) a[i]=read();
102     rep(i,1,n)
103       rep(j,1,n) f[++nu].x=i,f[nu].y=j,f[nu].num=read();
104     sort(f+1,f+nu+1,cmp);
105     dfs(1); 
106     rep(i,1,n) 
107       if (Ans[i]) { 
108         if (m>1) { cout<<i<<" "; m--;}
109         else {cout<<i; return 0;}
110       }
111     return 0;
112 }
View Code

 

 



B: 软件公司

时间限制: 1 Sec  内存限制: 128 MB
提交: 47  解决: 12
[提交][状态][讨论版]

题目描述

一家软件开发公司有两个项目,并且这两个项目都由相同数量的m个子项目组成,对于同一个项目,每个子项目都是相互独立且工作量相当的。由于时效性,两个项目必须同时被完成,如果其中一个完成的早了,那么这两个项目都会无效。
这家公司有n名程序员分配给这两个项目,每个子项目必须由一名程序员一次完成,多名程序员可以同时做同一个项目中的不同子项目
求公司完成两个项目的最少时间。

 

输入

第一行两个正整数n,m(1<=n<=100,1<=m<=100)。
接下来n行,每行包含两个整数,x和y。分别表示每个程序员完成第一个项目的子程序的时间,和完成第二个项目子程序的时间。每个子程序耗时也不超过100。

 

输出

包含一个整数,表示两个项目同时完成的时间。

 

样例输入

3 20
1 1
2 4
1 6

样例输出

18

提示

 

【样例解释】

    第一个人做18个2项目,耗时18;第二个人做2个1项目,2个2项目耗时12;第三个人做18个1项目,耗时18。

 

【数据范围】

对于30%的数据,n<=30.

对于60%的数据,n<=60.

 

 

来源

 
这题不用多说就知道是DP了,那这题怎么写呢?
先看30%的数据:
dp[i][x][y]表示到第i个人,第一个项目完成x个,第二个项目完成y个的最小时间,
dp[i][x][y]=min(dp[i][x][y],max(dp[i][x-i_][y-j_],i_*a[i]+j_*b[i])) 
耗时:n*m^4; PS:OJ跑的快过了50%,
 
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<vector>
 8 using namespace std;
 9 typedef long long ll;   
10 typedef long double ld;
11 typedef pair<int,int> pr;
12 const double pi=acos(-1);
13 #define rep(i,a,n) for(int i=a;i<=n;i++)
14 #define per(i,n,a) for(int i=n;i>=a;i--)
15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
16 #define clr(a) memset(a,0,sizeof(a))
17 #define pb push_back
18 #define mp make_pair
19 #define fi first
20 #define sc second
21 #define pq priority_queue
22 #define pqb priority_queue <int, vector<int>, less<int> >
23 #define pqs priority_queue <int, vector<int>, greater<int> >
24 #define vec vector
25 ld eps=1e-9;
26 ll pp=1000000007;
27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
29 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
31 ll read(){ ll ans=0; char last=' ',ch=getchar();
32 while(ch<'0' || ch>'9')last=ch,ch=getchar();
33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
34 if(last=='-')ans=-ans; return ans;
35 }
36 int a[200],b[200],dp[105][105][105]; 
37 int main()
38 {
39     int n=read(),m=read();
40     rep(i,1,n) a[i]=read(),b[i]=read();
41     rep(i,0,n)
42       rep(x,0,m)
43         rep(y,0,m)
44           dp[i][x][y]=1e+8; 
45     dp[0][0][0]=0;
46     rep(i,1,n)
47       rep(x,0,m)
48         rep(y,0,m)
49           rep(i_,0,x)
50             rep(j_,0,y)
51               dp[i][x][y]=min(dp[i][x][y],max(dp[i-1][x-i_][y-j_],i_*a[i]+j_*b[i]));
52     cout<<dp[n][m][m];
53 }
View Code

 

在看60%的数据:
这题有明显的二分性,所以枚举答案,在可以算出j_;
而dp表示能不能取到。耗时:log(m)*n*m^3;PS:OJ跑的还要快,就A了;
 
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<vector>
 8 using namespace std;
 9 typedef long long ll;   
10 typedef long double ld;
11 typedef pair<int,int> pr;
12 const double pi=acos(-1);
13 #define rep(i,a,n) for(int i=a;i<=n;i++)
14 #define per(i,n,a) for(int i=n;i>=a;i--)
15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
16 #define clr(a) memset(a,0,sizeof(a))
17 #define pb push_back
18 #define mp make_pair
19 #define fi first
20 #define sc second
21 #define pq priority_queue
22 #define pqb priority_queue <int, vector<int>, less<int> >
23 #define pqs priority_queue <int, vector<int>, greater<int> >
24 #define vec vector
25 ld eps=1e-9;
26 ll pp=1000000007;
27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
29 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
31 ll read(){ ll ans=0; char last=' ',ch=getchar();
32 while(ch<'0' || ch>'9')last=ch,ch=getchar();
33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
34 if(last=='-')ans=-ans; return ans;
35 }
36 int a[200],b[200],dp[105][105][105]; 
37 int main()
38 {
39     int n=read(),m=read();
40     rep(i,1,n) a[i]=read(),b[i]=read();
41     int r=1,l=100;
42     while (r<l){
43         int mid=(r+l)/2;
44         rep(i,0,n)
45           rep(x,0,m)
46             rep(y,0,m)
47               dp[i][x][y]=0;
48         dp[0][0][0]=1;
49         rep(i,1,n)
50           rep(x,0,m)
51             rep(y,0,m){
52               for (int i_=0;i_<=x && i_*a[i]<=mid;i_++){
53                 int j_=(mid-i_*a[i])/b[i];
54                 if (j_>=0) dp[i][x][y]=dp[i][x][y]|dp[i-1][x-i_][max(0,y-j_)];
55               }
56         }
57         if (dp[n][m][m]) l=mid;
58         else r=mid+1;
59     }
60     cout<<r;
61 }
View Code

 

最后满分算法:
不感觉TMD表示能不能取到很浪费吗!
于是乎,可以把一位y放进去,dp表示成能去到的y的最小值,
耗时:log(m)*n*m^2。
 
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<vector>
 8 using namespace std;
 9 typedef long long ll;   
10 typedef long double ld;
11 typedef pair<int,int> pr;
12 const double pi=acos(-1);
13 #define rep(i,a,n) for(int i=a;i<=n;i++)
14 #define per(i,n,a) for(int i=n;i>=a;i--)
15 #define Rep(i,u) for(int i=head[u];i;i=Next[i])
16 #define clr(a) memset(a,0,sizeof(a))
17 #define pb push_back
18 #define mp make_pair
19 #define fi first
20 #define sc second
21 #define pq priority_queue
22 #define pqb priority_queue <int, vector<int>, less<int> >
23 #define pqs priority_queue <int, vector<int>, greater<int> >
24 #define vec vector
25 ld eps=1e-9;
26 ll pp=1000000007;
27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
29 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; }
30 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
31 ll read(){ ll ans=0; char last=' ',ch=getchar();
32 while(ch<'0' || ch>'9')last=ch,ch=getchar();
33 while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
34 if(last=='-')ans=-ans; return ans;
35 }
36 int a[200],b[200],dp[105][105]; 
37 int main()
38 {
39     int n=read(),m=read();
40     rep(i,1,n) a[i]=read(),b[i]=read();
41     int r=1,l=100;
42     while (r<l){
43         int mid=(r+l)/2;
44         rep(i,0,n)
45           rep(x,0,m)
46               dp[i][x]=-1e+8;
47         dp[0][0]=0;
48         rep(i,1,n)
49           rep(x,0,m)
50               for (int i_=0;i_<=x && i_*a[i]<=mid;i_++){
51                 int j_=(mid-i_*a[i])/b[i];
52                 if (j_>=0) dp[i][x]=max(dp[i][x],dp[i-1][x-i_]+j_);
53               }
54         if (dp[n][m]>=m) l=mid;
55         else r=mid+1;
56     }
57     cout<<r;
58 }
View Code

 



2162: 摧毁巴士站

时间限制: 1 Sec  内存限制: 128 MB
提交: 25  解决: 3
[提交][状态][讨论版]

题目描述

Gabiluso是最伟大的间谍之一。现在,他试图完成一个“不可能完成”的使命――减缓Colugu的军队到达机场的时间。Colugu有n个公共汽车站和m条道路。每条道路直接连接两个巴士站,所有的道路都是单向的。为了保持空气洁净,政府禁止所有军用车辆,因此,军队必须乘搭巴士去机场。两个巴士站之间,可能有超过一条道路。如果一个公共汽车站被破坏时,所有连接该站的道路将无法运作。Gabiluso需要做的是摧毁了一些公共汽车站,使军队无法在K分钟内到达机场。一辆公交车通过一条道路,都是一分钟。所有巴士站的编号从1到n。1号巴士站是在军营,第n号站是机场。军队始终从第一站出发。第一站和第n站不能被破坏,这里有大量的防御力量。当然也没有从第一站到第n站的道路。
请帮助Gabiluso来计算能完成使命所需摧毁的最低数目的巴士站。

 

输入

第一行包含三个整数n,m,k (2<n<=50,0<m<=4000,0<k<1000)。
接下来m行,每行2个整数s和f,表示从站s到站f有一条路。

 

输出

输出最少需要摧毁的巴士站数目。

 

样例输入

5 7 3 
1 3 
3 4 
4 5 
1 2 
2 5 
1 4 
4 5

样例输出

2

提示

 

【数据规模】

30%的数据N<=15。

 

 

来源

 
本题网络流或大暴力(每次找最短路,枚举路上的点删不删)
 
PS:暴力懒得打了,网络流不会。

 

posted @ 2016-09-16 20:45  SXia  阅读(212)  评论(0编辑  收藏  举报