寻找数列(构造+拓扑)

寻找一个有n个整数的数列,满足下列条件:

其中任意连续p个数之和是正数。

其中任意连续q个数之和是负数。

若无法找到,则输出"No",否则输出一个数值最小的数列。

输入  n  p  q

输出  n个整数

 

样例:

输入:

5 4 3

输出:

2 2 -5 2 2

 

 

 

 

设: si——数列前i个数之和。

所以有

s[i]=a[1]+a[2]+...+a[i]

s[0]=0;

 

s[i+p]-s[i]>0 s[i+p]>s[i]

s[i+q]-s[i]<0 s[i+q]

构图:

点——i (0..n)

权——s[i]

边——当s[i]>s[j]时 有(i,j)

 

如n,p,q=6,5,3

 

寻找数列(构造+拓扑)_第1张图片

s[i]>s[i+3]

s[i+5]>s[i]

拓扑号: 0 1 2 3   4   5  6

            2 5 0 3   6   1  4

                  ↑ 这个我们知道。  而要最小、 所以往前一次递增,往后依次递减。

 s[i]  : 2 1 0 -1 -2 -3  -4

 

a[i]=s[i]-s[i-1]: 1  2  3  4  5  6

                      -3 5 -3 -3  5 -3

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
#include<stdio.h>
#include
<stdlib.h>
int n,p,q,i,j,k,g[100][100],ID[100],s[100],a[100];
int main(){
    freopen(
"寻找队列.in","r",stdin);
    freopen(
"寻找队列.out","w",stdout);
    scanf(
"%d%d%d",&n,&p,&q);
    
for (i=0;i<=n-p;i++){
        g[i
+p][i]=1;
        ID[i]
++;
    }
    
for (i=0;i<=n-q;i++){
        g[i][i
+q]=1;
        ID[i
+q]++;
    }

    i
=-1;
    
do{
        i
++; j=0;
        
while (j<=&& ID[j]!=0) j++;
        
if (j<=n){
            s[i]
=j; ID[j]=2147483647;
            a[j]
=i;
            
for (k=0;k<=n;k++)
                
if (g[j][k]==1) ID[k]--;
        }
    }
while(j<=&& i!=n);
    
if (i<n){
        printf(
"No\n");
        
return 0;
    }    
    
    
for(i=0;i<n;i++)
        printf(
"%d ",a[i]-a[i+1]);
    
return 0;
}

 

 

转载于:https://www.cnblogs.com/yanrui7098/archive/2009/11/22/1608267.html

你可能感兴趣的:(寻找数列(构造+拓扑))