zoukankan      html  css  js  c++  java
  • poj1093

    题意:给出一个句子和要求整理后每行包含的字符数,要求将其整理为一种总badness最小的形式。设每个空格长度为n,单个空格的badness计算公式为(n-1)^2。总badness等于所有空格的badness的总和。给出整理后的格式。在badness最小的前提下,在分配一行中的空格时要让前面的空格尽量少。如果一个单词单占一行,badness为500。

    分析:动态规划。f[i]表示前i个单词的最小badness是多少。f[i]=f[i-j]+cost(i-j,j);。cost(a,b)表示从单词a+1到单词b的放在一行中最小badness是多少。

    并用from[i]存储f[i]是从哪个位置计算得来的值,即最后一次更新f[i]时i-j是几,即f[i]所在行的上一行的最后一个单词是第几个。

    我们利用from数组可以求出最佳方案,然后按照题中要求输出即可。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    const int maxn = 1000;
    
    int n, wordsnum;
    string words[maxn];
    int sum[maxn];
    int f[maxn][maxn];
    int from[maxn][maxn];
    
    void turntowords(string st)
    {
        int i = 0;
    
        while (1)
        {
            i = 0;
            while (st[i] != ' ' && i < signed(st.length()))
                i++;
            words[wordsnum++] = st.substr(0, i);
            sum[wordsnum] = i + sum[wordsnum - 1];
            if (i == signed(st.length()))
                break;
            st.erase(0, i);
            while (st[0] == ' ')
                st.erase(0, 1);
        }
    }
    
    void init()
    {
        string st;
    
        wordsnum = 0;
        memset(sum, 0, sizeof(sum));
        getchar();
        while (1)
        {
            getline(cin, st);
            if (st == "")
                break;
            turntowords(st);
        }
    }
    
    int cost(int start, int end)
    {
        int left, right, tot, len;
    
        if (end - start == 1)
            return 500;
        tot = n - (sum[end] - sum[start]);
        len = tot / (end - start - 1);
        left = end - start - 1 - tot % (end - start - 1);
        right = tot % (end - start - 1);
        return left * (len - 1) * (len - 1) + right * len * len;
    }
    
    void work()
    {
        int i, j, k;
    
        memset(f, -1, sizeof(f));
        f[0][0] = 0;
        for (i = 1; i <= wordsnum; i++)
            for (j = 1; j <= wordsnum; j++)
                for (k = 1; k <= j && j - k >= i - 1 && n - (sum[j] - sum[j - k]) >= k - 1; k++)
                    if (f[i - 1][j - k] != -1 && (f[i][j] > f[i - 1][j - k] + cost(j - k, j) || f[i][j] == -1))
                    {
                        f[i][j] = f[i - 1][j - k] + cost(j - k, j);
                        from[i][j] = k;
                    }
    }
    
    void printline(int start, int end)
    {
        int left, tot, len, i, j;
    
        if (end - start == 1)
        {
            cout << words[start] << endl;
            return;
        }
        tot = n - (sum[end] - sum[start]);
        len = tot / (end - start - 1);
        left = end - start - 1 - tot % (end - start - 1);
        for (i = start; i < end - 1; i++)
        {
            cout << words[i];
            for (j = 0; j < len; j++)
                printf(" ");
            if (i - start + 1 > left)
                printf(" ");
        }
        cout << words[end - 1] << endl;
    }
    
    void output()
    {
        int i, best = 1000000000, besti;
    
        for (i = 0; i <= wordsnum; i++)
            if (f[i][wordsnum] < best && f[i][wordsnum] >= 0)
            {
                best = f[i][wordsnum];
                besti = i;
            }
        int line[maxn];
        int j = wordsnum;
        for (i = besti; i > 0; i--)
        {
            line[i] = from[i][j];
            j -= from[i][j];
        }
        j = 0;
        for (i = 1; i <= besti; i++)
        {
            printline(j, j + line[i]);
            j += line[i];
        }
        cout << endl;
    }
    
    int main()
    {
        //freopen("D:\t.txt", "r", stdin);
        while (cin >> n && n != 0)
        {
            init();
            work();
            output();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Mtk Ft6306 touch 驱动 .
    第一屏不显示懒加载的图片内容,这个方法可以搞定
    C#多线程中访问winform控件 (解决Winform 对象当前正在其他地方使用)
    变化的科技感十足的网站,推荐
    新年有感
    获取高精度时间注意事项 (QueryPerformanceCounter , QueryPerformanceFrequency)
    修改 TeamViewer ID 的方法
    VS2017离线安装包[百度云盘](收藏了)
    老子今天不加班,程序员也需要自由
    改变Eclipse 中代码字体大小
  • 原文地址:https://www.cnblogs.com/rainydays/p/3203984.html
Copyright © 2011-2022 走看看