Codeforces 976D
Posted 温和的提比略
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 976D相关的知识,希望对你有一定的参考价值。
题意略。
思路:构造题。
我们把全部的d[n]+1个点分作3部分来构造。
首先我们把原问题归约成构造d1、dn、和{d2 - d1,d3 - d1,.....,d[n-1] - d1}这样的问题,其中第三部分的构造相当于是原问题的子问题。
1.由本部向P2中每一个点都连接一条边,这样可以补上第三部分中每个元素都缺少的d1,现在相当于构造出了{d2,d3,....,d[n - 1]},还差d1和dn没构造出来。
2.用剩下的dn - d[n-1]来凑d1,P1向P2中每个点都连一条边,可以凑出d1。
3.现在P2内的点的度为dn - d[n-1] + d[n-1] - d1 + 1 = dn - (d1 - 1)。如果将P2内的点连成一个完全图,可以补上(d1 - 1),从而得到dn的值。
递归时的边界条件为l > r,或l == r。
1.l > r时,rst = 1,什么都不做就行。
2.l == r时,rst = d[l] + 1,将它连成一个完全图即符合题意。
rst表示当前问题的本部部分有多少个点,从而确定P1和P2在数组中的下标起始。
详见代码:
#include<bits/stdc++.h> #define maxn 350 #define maxn1 1050 using namespace std; int di[maxn],rst,n,cnt; vector<int> graph[maxn1]; void dfs(int l,int r){ if(l > r){ rst = 1; return; } if(l == r){ for(int i = 1;i <= di[l] + 1;++i){ for(int j = i + 1;j <= di[l] + 1;++j){ graph[i].push_back(j); ++cnt; } } rst = di[l] + 1; return; } int p1 = di[r] - di[r - 1],p2 = di[l]; for(int i = l + 1;i <= r - 1;++i) di[i] -= di[l]; dfs(l + 1,r - 1); for(int i = 1;i <= rst;++i){ for(int j = rst + p1 + 1;j <= rst + p1 + p2;++j){ graph[i].push_back(j); ++cnt; } } for(int i = rst + 1;i <= rst + p1;++i){ for(int j = rst + p1 + 1;j <= rst + p1 + p2;++j){ graph[i].push_back(j); ++cnt; } } for(int i = rst + p1 + 1;i <= rst + p1 + p2;++i){ for(int j = i + 1;j <= rst + p1 + p2;++j){ graph[i].push_back(j); ++cnt; } } rst += (p1 + p2); for(int i = l + 1;i <= r - 1;++i) di[i] += di[l]; return; } int main(){ scanf("%d",&n); for(int i = 1;i <= n;++i){ scanf("%d",&di[i]); } dfs(1,n); printf("%d\\n",cnt); for(int i = 1;i <= di[n];++i){ for(int j = 0;j < graph[i].size();++j){ printf("%d %d\\n",i,graph[i][j]); } } return 0; }
以上是关于Codeforces 976D的主要内容,如果未能解决你的问题,请参考以下文章
[Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3)][C. Playing Piano](代码片段
Codeforces 86C Genetic engineering(AC自动机+DP)
CodeForces 1005D Polycarp and Div 3(思维贪心dp)