【Hihocoder - offer编程练习赛93 套题题解】交错01串(贪心,暴力)方格矩阵高度(模拟)数对(STLmultiset)修整土地(网络流)
A:
題干:
時間限制:10000ms
單點時限:1000ms
內(nèi)存限制:256MB
描述
小Hi要將一個01串S傳輸給小Ho,由于S非常長,所以小Hi決定用長度為N的2個數(shù)組A = [A1, A2, ..., AN]和B = [B1, B2, ..., BN]表示S。 ?
具體來講,是指S由N段連續(xù)的字符串組成,其中第i段包含Ai個Bi。其中Bi可能是0或1。 ?
例如 A = [1, 2, 3, 4], B = [1, 0, 0, 1]表示S = "1000001111"。 ?
現(xiàn)在小Ho想把S變成一個01交錯的字符串。請你幫他計算他最少要改變S中多少個字符才能達成?
輸入
第一行包含一個整數(shù)N。 ?
第二行包含N個整數(shù),A1, A2, A3, ... AN。 ?
第三行包含N個整數(shù),B1, B2, B3, ... BN。 ?
1 <= N <= 100000 ?
1 <= Ai <= 100000 ?
0 <= Bi <= 1
輸出
一個整數(shù)代表答案
樣例輸入
4 1 2 3 4 1 0 0 1樣例輸出
4解題報告:
?
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; const int MAX = 2e5 + 5; int a[MAX],b[MAX]; int main() {int n;cin>>n;ll sum = 0;for(int i = 1; i<=n; i++) scanf("%d",a+i),sum += a[i]/2;for(int i = 1; i<=n; i++) scanf("%d",b+i);//開頭是1 ll ans1 = 0;bool sd = 1;for(int i = 1; i<=n; i++) {if(b[i] == sd) {ans1 += a[i]/2;if(a[i]&1) sd = !sd;}else {ans1 += (a[i]+1)/2;if(a[i]&1) sd = !sd; }}ll ans2 = 0;sd = 0;for(int i = 1; i<=n; i++) {if(b[i] == sd) {ans2 += a[i]/2;if(a[i]&1) sd = !sd;}else {ans2 += (a[i]+1)/2;if(a[i]&1) sd = !sd; }} printf("%lld\n",min(ans1,ans2));return 0 ;}B:
題干:
時間限制:10000ms
單點時限:1000ms
內(nèi)存限制:256MB
描述
小Hi有NxM的方格矩陣,每個方格的高度是Hij。例如如下是2x3的方格矩陣和每個方格的高度:
--> 1 3 4左 2 5 3視 ^圖 |前視圖左邊看過去,可以得到方格矩陣的左視圖L = [L1 ... LN];從前邊看過去,可以得到方格矩陣的前視圖F = [F1 ... FM]。 ?
例如上例中L = [4, 5], F = [2, 5, 4]。
現(xiàn)在小Ho不知道每個方格的高度,只知道這些方格的左視圖和前視圖。他發(fā)現(xiàn)只知道左視圖和前視圖并不一定能唯一確定一個方格矩陣。
例如
2 4 4 2 5 4的左視圖和前視圖也是L = [4, 5]和F = [2, 5, 4]。 ?
于是小Ho想知道,對于所有可能的方格矩陣,格子高度之和最大是多少。
輸入
第一行包含兩個整數(shù)N和M。 ?
第二行包含N個整數(shù)L1, L2, ... LN,代表左視圖。 ?
第三行包含M個整數(shù)F1, F2, ... FM,代表前視圖。
1 <= N, M <= 1000 ?
1 <= Li, Fi <= 1000
輸出
一個整數(shù)代表答案
樣例輸入
2 3 4 5 2 5 4樣例輸出
21解題報告:
N*M暴力跑就行了。枚舉每一個看他可以達到的最大值。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; const int MAX = 2e5 + 5; int n,m; int h[MAX],q[MAX]; int main() {ll ans = 0;cin>>n>>m;for(int i = 1; i<=n; i++) cin>>h[i];for(int i = 1; i<=m; i++) cin>>q[i];for(int i = 1; i<=n; i++) {for(int j = 1; j<=m; j++) {ans += min(h[i],q[j]);}}cout <<ans;return 0 ;}C:
題干:
時間限制:10000ms
單點時限:1000ms
內(nèi)存限制:256MB
描述
給定N個整數(shù)A1, A2, ... AN。現(xiàn)在小Ho可以任意從中取出兩個整數(shù)X,Y湊成一個數(shù)對(X, Y),只要滿足Y = 2X。 ?
如果每個Ai最多被取出一次,請你幫小Ho計算他最多能湊出多少個數(shù)對?
輸入
第一行包含一個整數(shù)N。 ?
第二行包含N個整數(shù)A1, A2, ... AN。 ?
1 <= N <= 100000 ?
1 <= Ai <= 100000
輸出
一個整數(shù)代表答案
樣例輸入
5 1 2 4 8 16樣例輸出
2解題報告:
? ?這題數(shù)據(jù)范圍沒有加滿,所以可以用數(shù)組來計數(shù)(AC代碼1),這題Ai加到1e18也可以做(AC代碼2)。
AC代碼1:
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll ans=0; int n; int a[100005]; int cnt[100005]; int main() {scanf("%d",&n);for(int i=0; i<n; i++)scanf("%d",&a[i]),cnt[a[i]]++;sort(a,a+n);for(int i=0; i<n; i++) {if(a[i]%2==0&&cnt[a[i]/2]) {ans++;cnt[a[i]/2]--;cnt[a[i]]--;}}cout<<ans;return 0; }AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; const int MAX = 2e5 + 5; multiset<int> ms; int a[MAX],n; int main() {int ans = 0;cin>>n;for(int i = 1; i<=n; i++) {cin>>a[i];ms.insert(a[i]);}auto it = ms.begin();for(int i = 1; i<=n/2; i++) { while(ms.find((*it)*2) == ms.end() && it != ms.end()) ++it;if(it != ms.end()) {auto itt = ms.find((*it)*2);ans++;ms.erase(itt);itt = it;++it;ms.erase(itt);}else break;}cout <<ans;return 0 ;}D:
題干:
時間限制:20000ms
單點時限:2000ms
內(nèi)存限制:256MB
描述
H市的土地如下圖所示,呈現(xiàn)NxM塊區(qū)域,每一塊區(qū)域都有自己的高度Hij。
+---+---+---+---+---+---+|H11|H12|H13|H14|...|H1M|+---+---+---+---+---+---+|H21|H22|H23|H24|...|H2M|+---+---+---+---+---+---+. . . . . . .|HN1|HN2|HN3|HN4|...|HNM|+---+---+---+---+---+---+為了使以后的城市交通比較便利,H市決定將土地進行平整,使得所有的區(qū)域高度相等。已知將1個單位的土地移動到相鄰的區(qū)域需要花費1的費用,同時當前區(qū)域的高度降低1,接收土地的區(qū)域高度增加1。那么將所有的區(qū)域調(diào)整到相同的高度所需的最小費用是多少呢?
輸入
第一行包含兩個整數(shù)N和M。 ?
以下N行包含一個NxM的矩陣H。
0 <= Hij <= 1000
1 <= N, M <= 50
輸出
一個整數(shù)代表答案
樣例輸入
2 2 3 4 6 7樣例輸出
4解題報告:
? ?一眼網(wǎng)絡流。先計算出最終平衡時所有點的高度值sum(可以計算出,相當于已知)。建圖:建一個起點連向所有可以高度減少的點,流量是h[i][j]-sum(因為他必須減少),費用是0;新建一個匯點,高度需要增加的點連向匯點,流量是sum-h[i][j],費用是0,那么這樣建圖首先保證了源點流出的流量==匯點流入的流量,這也就保證了流量不會丟失,也就是最大流就是這么大,所以滿足了我們需要求最小費用,的要求。相當于是我通過建圖,首先固定了最大流(因為新建的源點到新建的匯點,最大流肯定就是min(源點連出的所有的邊的流量之和,匯點流入的所有的邊的流量之和),而這兩者相同,所以最大流已經(jīng)確定了,就是源點連出的所有邊的流量之和,也就是源點流出的流量),然后跑模板去求最小費用就行了。
不過這題他數(shù)據(jù)錯了你敢信,,,給的范圍根本不是50*50的,,而且遠大于這個,,怪不得一直RE。。。
另一種建圖方式:起點到每一個點都有一個流量h[i][j]費用0的邊,每個點都到終點有一個流量sum費用0的邊,然后每個點向四周連邊。合法性的證明參考上一種建圖方式。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long using namespace std;const int MAXN = 70000; const int MAXM = 100005; const int INF = 0x3f3f3f3f; struct Edge {int to,next,cap,flow,cost; } edge[MAXM]; int head[MAXN],tol; int pre[MAXN],dis[MAXN]; bool vis[MAXN]; int n,m; int N;//節(jié)點總個數(shù),節(jié)點編號從 0 ~ N-1 void init(int n) {N = n;tol = 0;memset(head, -1,sizeof(head)); } void addedge(int u,int v,int cap,int cost) {edge[tol].to = v;edge[tol].cap = cap;edge[tol].cost = cost;edge[tol].flow = 0;edge[tol].next = head[u];head[u] = tol++;edge[tol].to = u;edge[tol].cap = 0;edge[tol].cost = -cost;edge[tol].flow = 0;edge[tol].next = head[v];head[v] = tol++; } bool spfa(int s,int t) {queue<int>q;for(int i = 0; i <= N; i++) {dis[i] = INF;vis[i] = false;pre[i] = -1;}dis[s] = 0;vis[s] = true;q.push(s);while(!q.empty()) {int u = q.front();q.pop();vis[u] = false;for(int i = head[u]; i !=-1; i = edge[i].next) {int v = edge[i].to;if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ) {dis[v] = dis[u] + edge[i].cost;pre[v] = i;if(!vis[v]) {vis[v] = true;q.push(v);}}}}if(pre[t] ==-1)return false;else return true;} //返回的是最大流,cost 存的是最小費用 int minCostMaxflow(int s,int t,int &cost) {int flow = 0;cost = 0;while(spfa(s,t)) {int Min = INF;for(int i = pre[t]; i !=-1; i = pre[edge[i^1].to]) {if(Min > edge[i].cap-edge[i].flow)Min = edge[i].cap-edge[i].flow;}for(int i = pre[t]; i !=-1; i = pre[edge[i^1].to]) {edge[i].flow += Min;edge[i^1].flow-= Min;cost += edge[i].cost * Min;}flow += Min;}return flow; } int nx[]={0,1,0,-1}; int ny[]={1,0,-1,0}; int id(int i,int j) {return (i-1)*m+j; } int h[555][555]; int main() {while(~scanf("%d%d",&n,&m)) {init(n*m+22);int st=0,ed=n*m+1,sum = 0; for(int i = 1; i<=n; i++) {for(int j = 1; j<=m; j++) {scanf("%d",&h[i][j]);sum += h[i][j];}}sum /= (n*m);for(int i = 1; i<=n; i++) {for(int j = 1; j<=m; j++) {if(h[i][j] > sum) addedge(st,id(i,j),h[i][j] - sum,0);else if(h[i][j] < sum) addedge(id(i,j),ed, sum - h[i][j],0);}}for(int i = 1; i<=n; i++) {for(int j = 1; j<=m; j++) {for(int k = 0; k<4; k++) {int tx = i + nx[k];int ty = j + ny[k];if(tx<1||tx>n||ty<1||ty>m) continue;addedge(id(i,j),id(tx,ty),INF,1);} }} int cost;int ans = minCostMaxflow(st,ed,cost);printf("%d\n",cost);}return 0 ; }?
總結
以上是生活随笔為你收集整理的【Hihocoder - offer编程练习赛93 套题题解】交错01串(贪心,暴力)方格矩阵高度(模拟)数对(STLmultiset)修整土地(网络流)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 申请信用卡面签是什么意思 信用卡面签技巧
- 下一篇: 【HDU - 4056】Draw a M