NYOJ 110 决斗(区间DP + 黑书例题)

题意:

http://acm.nyist.net/JudgeOnline/problem.php?pid=110

思路:

1. 区间DP的典型:meet[i][j] = true 的条件是中间存在 k 使得 meet[i][k] == true && meet[k][j] == true && i, j 至少有一个能战胜 k;

2. 由于题目是个环,可以破环为直线,比如:0 1 2 0 1 2 ,区间长度扩大了一倍;

 

#include <iostream>

#include <algorithm>

using namespace std;



int map[510][510], meet[1010][1010];



int main() {

    int cases;

    scanf("%d", &cases);

    while (cases--) {

        int n;

        scanf("%d", &n);

        for (int i = 0; i < n; i++)

            for (int j = 0; j < n; j++)

                scanf("%d", &map[i][j]);

        for (int i = 0; i < 2*n; i++) 

            meet[i][i] = meet[i][i+1] = true;



        for (int d = 2; d <= n; d++) {

            for (int i = 0, j = i+d; j < 2*n; i++, j++) {

                bool flag = false;

                for (int k = i + 1; k < j; k++) {

                    if (meet[i][k] && meet[k][j] && (map[i%n][k%n] || map[j%n][k%n])) {

                        flag = true; break;

                    } 

                }

                meet[i][j] = flag;

            }

        }

        int ans = 0;

        for (int i = 0; i < n; i++)

            if (meet[i][i+n]) ans += 1;

        printf("%d\n", ans);

    }

    return 0;

}

你可能感兴趣的:(dp)