• [cf1444D]Rectangular Polyline


    由于两种线段要交替出现,有解的必要条件即为$h=v$(以下均记为$n$)

    进一步的,再假设两种线段依次对应于向量$(a_{i},0)$和$(0,b_{i})$,根据题意要求向量长度为给定值且和为0,那么也即有$|a_{i}|=l_{i},|b_{i}|=p_{i}$且$sum_{i=1}^{n}a_{i}=sum_{i=1}^{n}b_{i}=0$

    使用背包判定是否存在这样的$a_{i}$和$b_{i}$,若不存在即无解,若存在则再求出任意一组

    (可以证明此时一定有解,以下即为构造)

    若$a_{i}$中的负数少于$b_{i}$则将两者全部取相反数,再将两者分别从大到小排序(其实只需要保证正数在负数前),最后将$(a_{i},b_{i})$作为一个整体极角排序,并依次选择$(a_{1},0),(0,b_{1}),(a_{2},0),...,(b_{n},0)$即可

    (代码实现上通过将两边分别合理排序使得其已经极角排序)

    不难发现,以此法最终方案一定是形如下图的形式,即合法

    时间复杂度为$o(frac{nC^{2}}{omega})$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 1005
     4 bitset<N*N>f[N];
     5 int t,n,m,a[N],b[N];
     6 int calc(int *a){
     7     int m=0;
     8     for(int i=1;i<=n;i++)m+=a[i];
     9     if (m&1)return 0;
    10     m>>=1;
    11     for(int i=1;i<=n;i++)f[i]=((f[i-1])|(f[i-1]<<a[i]));
    12     if (!f[n][m])return 0;
    13     for(int i=n;i;i--)
    14         if (!f[i-1][m]){
    15             m-=a[i];
    16             a[i]=-a[i];
    17         }
    18     return 1;
    19 }
    20 int main(){
    21     f[0][0]=1;
    22     scanf("%d",&t);
    23     while (t--){
    24         scanf("%d",&n);
    25         for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    26         scanf("%d",&m);
    27         for(int i=1;i<=m;i++)scanf("%d",&b[i]);
    28         if ((n!=m)||(!calc(a))||(!calc(b))){
    29             printf("No
    ");
    30             continue;
    31         }
    32         int cnt=0;
    33         for(int i=1;i<=n;i++)cnt+=(a[i]<0)-(b[i]<0);
    34         if (cnt<0){
    35             for(int i=1;i<=n;i++)a[i]=-a[i],b[i]=-b[i];
    36         }
    37         sort(a+1,a+n+1),reverse(a+1,a+n+1);
    38         sort(b+1,b+n+1),reverse(b+1,b+n+1);
    39         for(int i=1;i<=n+1;i++)
    40             if ((i>n)||(a[i]<0)){
    41                 reverse(b+1,b+i);
    42                 break;
    43             }
    44         for(int i=n;i>=0;i--)
    45             if ((!i)||(b[i]>0)){
    46                 reverse(a+i+1,a+n+1);
    47                 break;
    48             }
    49         printf("Yes
    ");
    50         for(int i=1,x=0,y=0;i<=n;i++){
    51             x+=a[i],printf("%d %d
    ",x,y);
    52             y+=b[i],printf("%d %d
    ",x,y);
    53         }
    54     }
    55     return 0;
    56 } 
    View Code
  • 相关阅读:
    switch_goto
    隐藏 窗口的整个 标题栏(包括右上角的关闭)
    asp的邦定表达式异常 <_ %_ = strParentid _%_>不能传到下个页面
    【收藏】default.rdp配置
    计算机网络中的性能指标
    当某个快捷键不能用时很可能是热键冲突
    java的FOR循环 打印三角形
    二进制 八进制 十进制 十六进制
    linux的vim编辑命令常用
    JIRA的备份
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15399758.html
Copyright © 2020-2023  润新知