2013 Pacific Northwest Region Programming Contest补题

A. Assignments

水题,随便写。

B. Bones’s Battery

二分油箱容积,判断是否符合。判断可行性时预处理各点两两间是否能一次走完,能的话在这两点间构建边权为1的边,完了后跑最短路得到最大加油次数,与k比较即可。

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn = 100 + 5;
 7 typedef long long ll;
 8 const ll inf = 0x3f3f3f3f;
 9 
10 ll mp[maxn][maxn];
11 int dp[maxn][maxn];
12 int n, m, K;
13 
14 void ini() {
15     for(int k=0;k<n;k++) {
16         for(int i=0;i<n;i++) {
17             mp[i][i] = 0;
18             for(int j=0;j<n;j++) {
19                 if(i==k || mp[i][k]==inf || mp[k][j]==inf) continue;
20                 mp[i][j] = min(mp[i][j], mp[i][k]+mp[k][j]);
21             }
22         }
23     }
24 }
25 
26 bool solve(ll x) {
27     for(int i=0;i<n;i++) {
28         for(int j=0;j<n;j++) 
29             dp[i][j] = mp[i][j]<=x?1:inf;
30     }
31     for(int k=0;k<n;k++) {
32         for(int i=0;i<n;i++) {
33             dp[i][i] = 0;
34             for(int j=0;j<n;j++) {
35                 if(i==k || dp[i][k]==inf||dp[k][j]==inf) continue;
36                 dp[i][j] = min(dp[i][j], dp[i][k]+dp[k][j]);
37             }
38         }
39     }
40     for(int i=0;i<n;i++) {
41         for(int j=0;j<n;j++) if(dp[i][j]>K) return 0;
42     }
43     return 1;
44 }
45 
46 int main() {
47     int T;
48     scanf("%d", &T);
49     while(T--) {
50         int x, y;
51         ll w, l=0, r=0;
52         scanf("%d%d%d", &n, &K, &m);
53         memset(mp, 0x3f, sizeof(mp));
54         for(int i=0;i<m;i++) {
55             scanf("%d%d%lld", &x, &y, &w);
56             mp[x][y] = mp[y][x] = w;
57             r+=w;
58         }
59         ini();
60         while(l<r) {
61             ll mid = l+r>>1;
62             if(solve(mid)) r=mid;
63             else l=mid+1;
64         }
65         printf("%lld\n", l);
66     }
67 }
View Code

C. Crusher’s Code

概率顺着走,概数倒着走,用dp[si]表示由si状态达到最终状态的平均步数,我们可以得到2个方程式:

第一种情况:

第二钟情况:

其中sj表示si能达到的状态,cnt表示共有多少个状态可达。

代码:

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<unordered_map>
 5 #include<iostream>
 6 using namespace std;
 7 const int maxn = 15;
 8 typedef double intd;
 9 
10 int a[maxn], b[maxn];
11 unordered_map<int,intd> dp[2];
12 
13 int n, ed;
14 
15 int Hash(int *arry) {
16     int rtn = 0;
17     for(int i=0;i<n;i++)    
18         rtn = rtn*8 + arry[i];
19     return rtn;
20 }
21 
22 intd Dp1() {
23     int sta = Hash(a);
24     if(sta == ed) return 0.0;
25     if(dp[0].count(sta)) return dp[0][sta];
26     intd sum = 0.0;
27     int cnt = 0;
28     for(int i=0;i<n;i++) {
29         for(int j=0;j<n;j++) if(a[min(i,j)]>a[max(i,j)]){
30             cnt ++;
31             swap(a[i], a[j]);
32             sum += Dp1();
33             swap(a[i], a[j]);
34         }
35     }
36     return dp[0][sta] = sum/(1.0*cnt) + n*n*1.0/(1.0*cnt);
37 }
38 
39 intd Dp2() {
40     int sta = Hash(a);
41     if(sta == ed) return 0.0;
42     if(dp[1].count(sta)) return dp[1][sta];
43     intd sum = 0.0;
44     int cnt = 0;
45     for(int i=0;i<n-1;i++) if(a[i]>a[i+1]){
46         cnt ++;
47         swap(a[i], a[i+1]);
48         sum += Dp2();
49         swap(a[i], a[i+1]);
50     }
51     return dp[1][sta] = sum/(1.0*cnt) + (n-1)*1.0/(1.0*cnt);
52 }
53 
54 int main() {
55     int T;
56     scanf("%d", &T);
57     while(T--) {
58         scanf("%d", &n);
59         for(int i=0;i<n;i++) {
60             scanf("%d", a+i);
61             b[i] = a[i];
62         }
63         sort(b, b+n);
64         for(int i=0;i<n;i++) {
65             int rk=lower_bound(b,b+n,a[i])-b;
66             a[i] = rk;
67         }
68         for(int i=0;i<n;i++)
69             b[i] = a[i];
70         sort(b, b+n);
71         int be = Hash(a);
72         ed = Hash(b);
73         dp[0].clear();
74         dp[1].clear();
75         Dp1();
76         Dp2();
77         printf("Monty %.6f Carlos %.6f\n", dp[0][be], dp[1][be]);
78     }
79     return 0;
80 }
View Code

D. Delta Quadrant

转换一下题意就知道这个题就是给定一棵树,删去k条边,保证其联通,求最小权值和,输出时乘上2即可。

随便取个点当作根节点,用dp[i][j]表示以节点i为根节点的字树中删去j条路径的最大权值,dfs遍历每个节点即可。

注意根节点可能会被删除,所以遍历时加个判断,如果某棵子树的节点树就为N-k就用它的权值和跟新答案。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 const int maxn = 1e4 + 5;
 8 const int maxm = 20 + 5;
 9 const ll inf = 0x3f3f3f3f3f3f;
10 
11 struct Node
12 {
13     int v, u, to;
14     ll w;
15 }p[maxn<<1];
16 int h[maxn];
17 int tot;
18 ll dp[maxn][maxm];
19 int N, k;
20 ll sum, ans;
21 
22 void ini()
23 {
24     tot = 0;
25     sum = 0;
26     memset(h, -1, sizeof(h));
27     memset(dp, 0, sizeof(dp));
28 }
29 
30 void add(int v,int u,ll w)
31 {
32     p[tot].v = v;
33     p[tot].u = u;
34     p[tot].w = w;
35     p[tot].to = h[v];
36     h[v] = tot++;
37 }
38 
39 void dfs(int v,int fa,int& cnt,ll& sw)
40 {
41     cnt = 1;
42     sw = 0;
43     for(int t=h[v];~t;t=p[t].to) {
44         int u = p[t].u;
45         if(u == fa) continue;
46         int cn;
47         ll sn;
48         dfs(u, v, cn, sn);
49         if(cn == N-k)
50             ans = min(ans, sn*2);
51 
52         if(cn <= k)
53             dp[u][cn] = dp[u][cn-1]+p[t].w;
54         sw += p[t].w + sn;
55         cnt += cn;
56         for(int i=k;i>=0;i--) {
57             ll maxs = 0;
58             for(int j=0;j<=i;j++)
59                 maxs = max(maxs, dp[v][j]+dp[u][i-j]);
60             dp[v][i] = maxs;
61         }
62     }
63 }
64 
65 int main()
66 {
67     int T;
68     scanf("%d", &T);
69     while(T--) {
70         ini();
71         scanf("%d%d", &N, &k);
72         for(int i=0;i<N-1;i++) {
73             int v, u;
74             ll w;
75             scanf("%d%d%lld", &v, &u, &w);
76             add(v, u, w);
77             add(u, v, w);
78             sum += w;
79         }
80         int cnt;
81         ll sn;
82         ans = inf;
83         dfs(0, 0, cnt, sn);
84         if(cnt==N-k) {
85             printf("%lld\n", sum*2);
86             continue;
87         }
88         for(int i=0;i<N;i++)
89             ans = min(ans, 2*sum-2*dp[i][k]);
90         printf("%lld\n", ans);
91     }
92     return 0;
93 }
View Code

 E. Enterprising Escape

水题,优先队列一下就行。

F. Federation Favorites

水水水,暴力即可。

G. Federation Favorites

H2O,直接写。

H. Holodeck Hacking

待补。

I. Interstellar Trade

待补。

J. Janeway’s Journey

挖坑。

K. Klingon Warfare

挖坑。

L. Languages

水题,暴力匹配。

M. Mass Production

待补。

猜你喜欢

转载自www.cnblogs.com/UtopioSPH001/p/9028182.html