洛谷 P2294 【[HNOI2005]狡猾的商人】

题目链接——> P2294 [HNOI2005]狡猾的商人

写完看了一下题解区发现用区间DP的不多,也有一些缺陷,在此就来完善一番。

题目大致释意:若无法给出一组数满足给出的 mm 个条件,则输出 false ,反之则输出 true 。

给出数组 a[i][j]a[i][j] 表示区间 ii 到 jj 的区间和。初始值设为 inf 。

于是我们给出三重循环,第一重枚举每次区间长度,第二重枚举左端点, 第三重枚举左右端点之间的位置。 ii 表示左端点, jj 表示右端点, kk 表示区间长度, ll 表示左右端点之间的位置。我们可以从中知道 a[i][j]=a[i][l]+a[l+1][j]a[i][j]=a[i][l]+a[l+1][j] 的递推式。如果 a[i][j]a[i][j] 与已确定的 a[i][l] + a[l + 1][j]a[i][l]+a[l+1][j] 不同,则可直接退出。同时我们可以在一开始判重,若不一样,则可直接退出。

具体详见代码——>

#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 123456789//定义

using namespace std;

int w, n, m, a[105][105], p;

int main(){
    scanf("%d",&w);
    while(w--){
        scanf("%d%d",&n,&m);
        p = 1;
        for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++) a[i][j] = inf;//别忘了赋初值哦~
        for(int i = 1; i <= m; i++){
            int x, y, z;
            scanf("%d%d%d",&x,&y,&z);
            if(a[x][y] == inf || a[x][y] == z)//从读入开始判断
            a[x][y] = z;
            else p = 0;
        }
        if(p)
        for(int k = 1; k <= n; k++){
            for(int i = 1; i + k <= n; i++){
                int j = k + i;
                for(int l = i; l < j; l++){//DP主体
                    if(a[i][l] != inf && a[l + 1][j] != inf){//若已确定两个子区间
                        if(a[i][j] == inf) a[i][j] = a[i][l] + a[l + 1][j];//未有则赋值,已有则比较
                        else if(a[i][j] != a[i][l] + a[l + 1][j]){
                            p = 0;
                            goto there;//若不同,直接退出
                        }
                    }
                }
            }
        }
        there:;
        if(p) printf("true\n");
        else printf("false\n");
    }
    return 0;
} 

观察到 n < 100n<100 , w < 100w<100 , 足够我们跑了。不吸氧333ms足以满足需求。

撒花完结╰( ´・ω・)つ──☆✿✿✿

发布了5 篇原创文章 · 获赞 6 · 访问量 155

猜你喜欢

转载自blog.csdn.net/pikabi/article/details/105293169