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)如果有神犇能一語道破 , 請不吝賜教:-)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章