1. 程式人生 > >P3974 [TJOI2015]組合數學

P3974 [TJOI2015]組合數學

100% strong 智商 ++ lin main 合數 一次 for

P3974 [TJOI2015]組合數學

題目描述

為了提高智商,ZJY開始學習組合數學。某一天她解決了這樣一個問題:給一個網格圖,其中某些格子有財寶。每次從左上角出發,只能往右或下走。問至少要走幾次才可能把財寶全撿完。

但是她還不知足,想到了這個問題的一個變形:假設每個格子中有好多塊財寶,而每一次經過一個格子至多只能撿走一塊財寶,其他條件不變,至少要走幾次才可能把財寶全撿完?

這次她不會做了,你能幫幫她嗎?

輸入輸出格式

輸入格式:

第一行為一個正整數t,表示數據組數

每組數據的第一行是兩個正整數n和m,表示這個網格圖有n行m列。

接下來n行,每行m個非負整數,表示這個格子中的財寶數量(0表示沒有財寶)。

輸出格式:

對於每組數據,輸出一個整數,表示至少走的次數。

輸入輸出樣例

輸入樣例#1:
1
3 3
0 1 5
5 0 0
1 0 0
輸出樣例#1:
10

數據範圍

對於30%的數據,n≤5.m≤5,每個格子中的財寶數不超過5塊。

對於50%的數據,n≤100,m≤100,每個格子中的財寶數不超過1000塊

對於100%的數據,n≤1000,m≤1000,每個格子中的財寶不超過10^6塊

————————————————————————————————————————————————————————

首先DZY tql!OTZ

Dilworth定理:對於一個偏序集,最少鏈劃分等於最長反鏈長度。

Dilworth定理的對偶定理:對於一個偏序集,其最少反鏈劃分數等於其最長鏈的長度。

推論:DAG的最小鏈覆蓋=最大點獨立集

顯然題目要求求出最小鏈覆蓋

由於題目限制只能向右/下走,所以題目中的最大點獨立集一定是任意兩點都滿足左下和右上的對應關系,兩兩不可到達。

dp搞一下

code

#include<iostream>
int T, n, m, a[1010][1010], f[1010][1010];
int main() {
    std::cin >> T;
    
while(T -- ){ std::cin >> n >> m; for (int i = 1; i <= n; ++ i) for (int j = 1;j <= m; ++ j) std::cin >> a[i][j]; for (int i = 1; i <= n; ++ i) for (int j = m; j ; -- j) f[i][j] = std::max(f[i - 1][j + 1] + a[i][j], std::max(f[i - 1][j], f[i][j + 1])); std::cout << f[n][1] << std::endl; } return 0; }

P3974 [TJOI2015]組合數學