UVA

来源:互联网 发布:个人定位软件 编辑:程序博客网 时间:2024/06/06 12:48

题目网址点击打开链接

妈耶真的是这个想法太奇妙;

以前拓扑排序不太懂。这里加几个关于拓扑排序的博客。有一篇代码虽然是java,但是思想是不错的点击打开链接

点击打开链接;


解题思路:

把题目转化成已知各个前缀和的大小关系,求每个前缀和的值。s(i, j) 符号为正的话,表示a[i]+a[i+1] +.. a[j] > 0,即前缀和sum[j] - sum[i-1] > 0,即sum[j] > sum[i-1],知道了大小关系,把他的大小顺序看成是序列,因此是          sum[j] - >sum[i-1],所以对于i-1这一位入度要加,然后建立j - > i-a的路径;

处理完整个串之后就会建立一个偏序的图集;然后进行拓扑排序,因为题目要保证a序列每个数绝对值不大于10,所以令最大的数的值为10,然后逐个减一即可

每一位的值可以通过sum【i】-sum【i-1】求得

#include <iostream>#include <cstring>#include <string>#include <cstdio>#include<algorithm>#include<vector>#include<set>using namespace std;const int maxn=20+5;int vis[maxn];int inter[maxn];int sum[maxn];int mp[maxn][maxn];string s;int n;int main(){    int T;    cin>>T;    while(T--)    {        cin>>n;        cin>>s;        memset(vis,0,sizeof(vis));        memset(inter,0,sizeof(inter));        memset(sum,0,sizeof(sum));        memset(mp,0,sizeof(mp));        int cur=0;        for(int i=1;i<=n;i++)            for(int j=i;j<=n;j++)           {             if(s[cur]=='+')               {                   inter[i-1]++;                   mp[j][i-1]=1;               }             else if(s[cur]=='-')               {                   inter[j]++;                   mp[i-1][j]=1;               }               cur++;            }       // for(int i=0;i<=n;i++)          //  cout<<inter[i]<<" ";      //  cout<<endl;        int tot=0,now=10;        while(tot<=n)        {            for(int i=0;i<=n;i++)                if(!inter[i])               {                vis[i]=1;                inter[i]=-1;                tot++;                sum[i]=now;               }            now--;            for(int i=0;i<=n;i++)            {                if(vis[i])                {                    for(int j=0;j<=n;j++)                    if(mp[i][j])                    {                        inter[j]--;                    }                    vis[i]=0;                }            }        }        for(int i=1;i<=n;i++)        {            if(i!=1)                cout<<" ";            cout<<sum[i]-sum[i-1];        }        cout<<endl;    }    return 0;}


还有一种更加直接的做法:

#include <iostream>#include <cstring>#include <string>#include <cstdio>#include<algorithm>#include<vector>#include<set>using namespace std;const int maxn=20;const int maxd=1000+5;int N,M,K;int len,t,n,sum[maxn];string s;int main(){  scanf("%d",&t);  while(t--)  {      cin>>n;      memset(sum,0,sizeof(sum));      cin>>s;      len=0;      for(int i=1;i<=n;i++)        for(int j=i;j<=n;j++)      {          if(s[len]=='+') sum[i-1]--;          else if(s[len]=='-') sum[j]--;          len++;      }      for(int i=1;i<=n;i++)      {          if(i!=1)            cout<<" ";          cout<<sum[i]-sum[i-1];      }      cout<<endl;  }      //  cout<<res<<endl;    return 0;}



原创粉丝点击