NOIP模拟 7.04
魔术球问题弱化版(ball.c/.cpp/.pas)
【题目描述】
假设有 n 根柱子,现要按下述规则在这 n 根柱子中依次放入编号为 1,2,3,…的球。
(1)每次只能在某根柱子的最上面放球。
(2)在同一根柱子中,任何 2 个相邻球的编号之和为完全平方数。
试设计一个算法,计算出在 n 根柱子上最多能放多少个球。例如,在 4 根柱子上最多可放 11 个球。
对于给定的 n,计算在 n 根柱子上最多能放多少个球。
【输入描述】
第 1 行有 1 个正整数 n,表示柱子数。
【输出描述】
一行表示可以放的最大球数
4
样例输出。
样例输入
11
题目限制(为什么说弱化版就在这里)
N<=60,时限为3s
【题解】
暴力。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <cmath> 8 9 const int INF = 0x3f3f3f3f; 10 const int MAXN = 60 + 10; 11 12 inline void read(long long &x) 13 { 14 x = 0;char ch = getchar();char c = ch; 15 while(ch > '9' || ch < '0')c = ch, ch = getchar(); 16 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 17 if(c == '-')x = -x; 18 } 19 20 long long ans,num[MAXN],n; 21 22 void dfs(int step) 23 { 24 for(int i = 1;i <= n;++ i) 25 { 26 if(!num[i]) 27 { 28 num[i] = step; 29 ans = step; 30 dfs(step + 1); 31 return; 32 } 33 int k = sqrt(num[i] + step); 34 if(k * k == num[i] + step) 35 { 36 ans = step; 37 num[i] = step; 38 dfs(step + 1); 39 break; 40 } 41 } 42 return; 43 } 44 45 int main() 46 { 47 read(n); 48 dfs(1); 49 printf("%lld", ans); 50 return 0; 51 }
2.征兵(conscription.c/.cpp/.pas)
一个国王,他拥有一个国家。最近他因为国库里钱太多了,闲着蛋疼要征集一只部队要保卫国家。他选定了N个女兵和M个男兵,但事实上每征集一个兵他就要花10000RMB,即使国库里钱再多也伤不起啊。他发现,某男兵和某女兵之间有某种关系(往正常方面想,一共R种关系),这种关系可以使KING少花一些钱就可以征集到兵,不过国王也知道,在征兵的时候,每一个兵只能使用一种关系来少花钱。这时国王向你求助,问他最少要花多少的钱。
读入(conscription.in)
第一行:T,一共T组数据。
接下来T组数据,
第一行包括N,M,R
接下来的R行 包括Xi,Yi,Vi 表示如果招了第Xi个女兵,再招第Yi个男兵能省Vi元(同样表示如果招了第Yi个男兵,再招第Xi个女兵能也省Vi元)
输出(conscription.out)
共T行,表示每组数据的最终花费是多少(因为国库里的钱只有2^31-1,所以保证最终花费在maxlongint范围内)
样例输入
2
5 5 8
4 3 6831
1 3 4583
0 0 6592
0 1 3063
3 3 4975
1 3 2049
4 2 2104
2 2 781
5 5 10
2 4 9820
3 2 6236
3 1 8864
2 4 8326
2 0 5156
2 0 1463
4 1 2439
0 4 4373
3 4 8889
2 4 3133
样例输出
71071
54223
数据范围
数据保证
T<=5 ,m,n<=10000,r<=50000,Xi<=m,Yi<=n,Vi<=10000,结果<=2^31-1
【题解】
最大生成树。开始读错题了,以为是KM。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 8 const int INF = 0x3f3f3f3f; 9 const int MAXN = 1000000 + 10; 10 const int MAXM = 1000000 + 10; 11 12 inline void read(int &x) 13 { 14 x = 0;char ch = getchar();char c = ch; 15 while(ch > '9' || ch < '0')c = ch, ch = getchar(); 16 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 17 if(c == '-')x = -x; 18 } 19 20 int u[MAXM],v[MAXM],w[MAXM],cnt[MAXM]; 21 int t,n,m,r; 22 int fa[MAXN]; 23 long long ans; 24 25 bool cmp(int a, int b) 26 { 27 return w[a] >= w[b]; 28 } 29 30 int find(int x) 31 { 32 return x == fa[x] ? x : fa[x] = find(fa[x]); 33 } 34 35 int main() 36 { 37 read(t); 38 for(;t;--t) 39 { 40 ans = 0; 41 read(n);read(m);read(r); 42 int tmp = (n + m) << 1; 43 for(register int i = 0;i <= tmp;++ i) 44 fa[i] = i; 45 for(register int i = 0;i <= r;++ i) 46 cnt[i] = i; 47 for(register int i = 1; i <= r;++ i) 48 { 49 read(u[i]);read(v[i]);read(w[i]); 50 u[i] = u[i] << 1; 51 v[i] = v[i] << 1 | 1; 52 } 53 std::sort(cnt + 1, cnt + 1 + r, cmp); 54 for(register int i = 1;i <= r;++ i) 55 { 56 int x = find(u[cnt[i]]); 57 int y = find(v[cnt[i]]); 58 if(x != y) 59 { 60 ans += w[cnt[i]]; 61 fa[x] = y; 62 } 63 } 64 printf("%lld\n", (long long)(n + m) * 10000 - ans) ; 65 } 66 return 0; 67 }
3.坑爹的GPS(gpsduel.c/.cpp/.pas)
有一天,FJ买了一辆车,但是,他一手下载了两个GPS系统。好了现在麻烦的事情来了,GPS有一个功能大概大家也知道,如果FJ没有按照GPS内置地图的最短路走,GPS就会报错来骚扰你。现在FJ准备从他的农舍(在1这个点)开车到他的谷屋(n这个点)。FJ给了你两个GPS系统内置地图的信息,他想知道,他最少会听到多少次报错(如果FJ走的路同时不满足两个GPS,报错次数+2)
读入:第一行:n,k;n表示有FJ的谷屋在哪,同时保证GPS内置地图里的点没有超过n的点。K表示GPS内置地图里的路有多少条,如果两个点没有连接则表明这不是一条通路。
接下来k行,每行4个数X,Y,A,B分别表示从X到Y在第一个GPS地图里的距离是A,在第二个GPS地图里的是B。注意由于地形的其他因素GPS给出的边是有向边。
输出:一个值,表示FJ最少听到的报错次数。
样例输入:
5 7
3 4 7 1
1 3 2 20
1 4 17 18
4 5 25 3
1 2 10 1
3 5 4 14
2 4 6 5
样例输出:
1
解释
FJ选择的路线是1 2 4 5,但是GPS 1认为的最短路是1到3,所以报错一次,对于剩下的2 4 5,两个GPS都不会报错。
数据范围
N<=10000,至于路有多少条自己算吧。数据保证所有的距离都在2^31-1以内。
来源
USACO 2014年 全美公开赛银组第二题(各位轻虐银组题)
【题解】
三次最短路。
先建反图,求出每个点到终点的最短路。然后求走每条边会引起的错误值的变化,再求最短路即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 8 const int INF = 0x3f3f3f3f; 9 const int MAXN = 200000 + 10; 10 const int MAXQ = 300000 + 10; 11 const int MAXM = 1000000 + 10; 12 13 inline void read(int &x) 14 { 15 x = 0;char ch = getchar();char c = ch; 16 while(ch > '9' || ch < '0')c = ch, ch = getchar(); 17 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 18 if(c == '-')x = -x; 19 } 20 21 struct Edge 22 { 23 int u,v,next,w; 24 }edge1[MAXM],edge2[MAXM],edge3[MAXM]; 25 int head1[MAXN],head2[MAXN],head3[MAXN],cnt1,cnt2,cnt3; 26 int b1[MAXN],b2[MAXN],b3[MAXN]; 27 long long d1[MAXN],d2[MAXN],d3[MAXN]; 28 int n,m; 29 30 void insert1(int a, int b, int c){edge1[++cnt1] = Edge{a, b, head1[a], c};head1[a] = cnt1;} 31 void insert2(int a, int b, int c){edge2[++cnt2] = Edge{a, b, head2[a], c};head2[a] = cnt2;} 32 void insert3(int a, int b, int c){edge3[++cnt3] = Edge{a, b, head3[a], c};head3[a] = cnt3;} 33 34 std::queue<int> q; 35 36 void SPFA1() 37 { 38 memset(d1, 0x3f, sizeof(d1)); 39 q.push(n); 40 b1[n] = 1; 41 d1[n] = 0; 42 register int pos; 43 while(!q.empty()) 44 { 45 int u = q.front(); 46 q.pop(); 47 b1[u] = 0; 48 for(pos = head1[u];pos;pos = edge1[pos].next) 49 { 50 int v = edge1[pos].v; 51 if(d1[v] > d1[u] + edge1[pos].w) 52 { 53 d1[v] = d1[u] + edge1[pos].w; 54 if(!b1[v]) 55 { 56 q.push(v); 57 b1[v] = 1; 58 } 59 } 60 } 61 } 62 } 63 64 void SPFA2() 65 { 66 memset(d2, 0x3f, sizeof(d2)); 67 q.push(n); 68 b2[n] = 1; 69 d2[n] = 0; 70 register int pos; 71 while(!q.empty()) 72 { 73 int u = q.front(); 74 q.pop(); 75 b2[u] = 0; 76 for(pos = head2[u];pos;pos = edge2[pos].next) 77 { 78 int v = edge2[pos].v; 79 if(d2[v] > d2[u] + edge2[pos].w) 80 { 81 d2[v] = d2[u] + edge2[pos].w; 82 if(!b2[v]) 83 { 84 q.push(v); 85 b2[v] = 1; 86 } 87 } 88 } 89 } 90 } 91 92 void SPFA3() 93 { 94 memset(d3, 0x3f, sizeof(d3)); 95 q.push(1); 96 b3[1] = 1; 97 d3[1] = 0; 98 register int pos; 99 while(!q.empty()) 100 { 101 int u = q.front(); 102 q.pop(); 103 b3[u] = 0; 104 for(pos = head3[u];pos;pos = edge3[pos].next) 105 { 106 int v = edge3[pos].v; 107 if(d3[v] > d3[u] + edge3[pos].w) 108 { 109 d3[v] = d3[u] + edge3[pos].w; 110 if(!b3[v]) 111 { 112 q.push(v); 113 b3[v] = 1; 114 } 115 } 116 } 117 } 118 } 119 120 int main() 121 { 122 read(n);read(m); 123 register int tmp1, tmp2, tmp3, tmp4,i; 124 for(i = 1;i <= m; ++ i) 125 { 126 read(tmp1);read(tmp2);read(tmp3);read(tmp4); 127 insert1(tmp2, tmp1, tmp3); 128 insert2(tmp2, tmp1, tmp4); 129 insert3(tmp1, tmp2, 0); 130 } 131 SPFA1(); 132 SPFA2(); 133 for(int i = 1;i <= cnt3;++ i) 134 { 135 tmp1 = edge3[i].v;tmp2 = edge3[i].u; 136 if(d1[tmp1] + edge1[i].w > d1[tmp2]) ++edge3[i].w; 137 if(d2[tmp1] + edge2[i].w > d2[tmp2]) ++edge3[i].w; 138 } 139 SPFA3(); 140 printf("%lld", d3[n]); 141 return 0; 142 }