BZOJ 3997 TJOI2015 组合数学

此题贪心可解……

提示:
1. 对于一个格子而言 , 其实只有两种方式能够走到他
2. 如果把每一次走当作水流流过的话 , 那么水流最好能够停在左边 , 因为这样的选择空间更大
3. 如果说应该先处理方案数最少的点 , 那么应该是右上角 , 因为要到那个点只有一条路径

代码后详解:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <cassert>

using namespace std;
const int maxn = 1100;
int T , n , m;
int g[maxn][maxn];
int f[maxn];
int main(int argc, char *argv[]) {

    cin>>T;
    while(T--)
    {
        cin>>n>>m;

        memset(f, 0, sizeof(f));
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d" , &g[i][j]);

        int res = 0;
        for(int i=1;i<=n;i++)
        {
            int tmp = 0 , req , have , now;
            for(int j=m;j>=1;j--)
            {
                req = max(tmp , g[i][j]);
                have = max(f[j] , req);
                now = f[j];

                f[j] = have - tmp;
                tmp = have - now;
            }
            res += tmp;
        }
        cout<<res<<endl;
    }

    return 0;
}

总体思路是从上往下一行行的扫。
tmp 表示如果要满足当前格子的要求 , 左边至少需要流给我多少流量。 我们从右往左计算 tmp 这样对于每一行水流就停在了最佳位置(也就是尽量靠左)。

网上很多DP的递推式和我的很相似 , 但是我不知道其中的联系(网上的做法好高大上啊QAQ)如果有神犇能一语道破 , 请不吝赐教:-)

你可能感兴趣的:(贪心)