• [luoguP1415] 拆分数列(DP)


    传送门

    t(i,j)表示下标从i到j的数

    d[i]表示以i结尾的最小的数的下标

    d[i]=max(j) (1<=j<=i && t(d[j-1],j-1)<t(j,i))

    这样从1到n一遍DP可以求出末尾最小的数

    f[i]表示以i开头的最大的数的下标

    f[i]=max(j) (i<=j<=n && t(i,j)<t(j+1,d[j+1]))

    边界为f[d[n]]=n

    这样从d[n]-1到1一遍DP可以求出开头最大的数,第二个最大的数。。。

    注意前导0的情况

    #include <cstdio>
    #include <cstring>
    #define N 1001
    
    int n;
    char s[N];
    int d[N], f[N];
    //d[i]表示以i结尾的数,满足条件的最小数 
    //f[i]表示以i开头的数,满足条件的最大数 
    //s[i][j]表示从i到j的数是多少 
    
    inline int cmp(int x1, int y1, int x2, int y2)
    {
    	int i, j;
    	while(s[x1] == '0') x1++;
    	while(s[x2] == '0') x2++;
    	if(y1 - x1 == y2 - x2)
    	{
    		for(i = x1, j = x2; i <= y1; i++, j++)
    		{
    			if(s[i] > s[j]) return 1;
    			if(s[i] < s[j]) return 2;
    		}
    		return 0;	
    	}
    	if(y1 - x1 > y2 - x2) return 1;
    	if(y1 - x1 < y2 - x2) return 2;
    }
    
    int main()
    {
    	int i, j, k;
    	scanf("%s", s + 1);
    	n = strlen(s + 1);
    	for(i = 1; i <= n; i++)
    		for(j = i; j >= 1; j--)
    			if(cmp(j, i, d[j - 1], j - 1) == 1)
    			{
    				d[i] = j;
    				break;
    			}
    	while(s[d[n] - 1] == '0') d[n]--;
    	for(i = d[n]; i <= n; i++) f[i] = n;
    	for(i = d[n] - 1; i >= 1; i--)
    	{
    		k = n;
    		for(j = i; j <= n; j++)
    			if(cmp(i, j, j + 1, f[j + 1]) == 2)
    				k = j;
    		f[i] = k;
    	}
    	if(cmp(1, n, d[n], n) == 0)
    	{
    		printf("%s", s + 1);
    		return 0;
    	}
    	j = 1;
    	while(j <= n)
    	{
    		for(i = j; i <= f[j]; i++)
    			printf("%c", s[i]);
    		j = f[j] + 1;
    		if(j <= n) putchar(',');
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Flask、Vue部署总结
    Recat教程(二)
    C第一个程序
    React教程(一)
    Flask+uwsgi+nginx 部署
    使用Dockerfile部署简单的应用
    Typescript搭建开发环境
    Typescript模块化/命名空间/装饰器
    Typescript的泛型/泛型接口
    修改git密码后,终端fatal: Authentication failed for'http://xxx/xxx.git'
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7609514.html
Copyright © 2020-2023  润新知