SHU_OJ 1929:Yaoge的英语成绩题解

<pre name="code" class="cpp"><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">Yaoge和小伙伴们终于拿到了英语测试的成绩,大家开始讨论起各自的成绩,然而Yaoge身边都是智(yan)商(zhi)报表的同学们,他们不喜欢报出自己的成绩,只会说“我至少有XX分”,“我比XX至少高XX分”。</span>
 

作为Yaoge的朋友,你想知道他的成绩,于是你整理出了这两类信息:

1. A的成绩至少是X分。(ScoreA >= X)

2. A至少比B高X分。(ScoreA - ScoreB >= X)

利用这些信息,请求出Yaoge的英语成绩至少为多少分。

*注意每一位同学的分数都必须是非负整数。

 

Input

 

第一行是一个整数T,表示数组组数(T<=20)。

每一组数据第一行有三个整数N、P、Q,表示总人数为N,其中一直的第一类信息有P条,第二类信息有Q条。

(1 <= N <= 100, 0 <= P <= N, 0 <= Q <= 1000)

之后先有P行,每行有两个整数A、X,表示A的成绩至少为X分。

接着有Q行,每行有三个整数A、B、X,表示A至少比B高X分。

(1 <= A, B <=N,  1 <= X <= 1000)

*A、B表示同学的编号,其中1号表示Yaoge。

Output

 

对于每一组数据,输出一行整数,表示Yaoge的成绩的最小可能值。

Sample Input

2

1 0 0

3 1 2

2 570

3 2 30

1 3 112

 

Sample Output


0

712

 

HINT

update: 注意可能有重边!

 

Source

Curs0r

更改:本题是求两个点之间的最长路径。构造有向无环图,然后floyd直接求。或者构造拓扑排序,用动态规划求解。

#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>
#define INF 0x3f3f3f3f
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
#define M_PI 3.14159265358979323846
#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define X first
#define Y second
#define MAX_V 10101
#define maxn 10
#define lowbit(X) (X & (-X))
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
typedef pair<PII,int>PPI;
/************************************************
********************头文件**********************
************************************************/
//有向无环图求最长路径
int G[101][101]; 
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,p,q;
        cin>>n>>p>>q;
        memset(G,-INF,sizeof(G)); 
        int a,b,x;
        REP(i,n+1)G[i][0] = 0;//题中条件
        REP(i,p)
        {
            cin>>a>>x;
            G[a][0] = max(G[a][0],x);
        }
        REP(i,q)
        {
            cin>>a>>b>>x;
            G[a][b] = max(G[a][b],x);
        }
        REP(i,n+1) 
        REP(j,n+1)
        REP(k,n+1) 
        G[j][k] = max(G[j][k],G[j][i]+G[i][k]);

        cout<<G[1][0]<<endl;
    }
    return 0;
}



这道题对于初学竞赛的人来说还是要费一番脑筋的。我也是花了将近两个小时才把这道题搞定(我也是菜鸟)。大部分要说的内容标注在注释上,代码如下:

#include <iostream> 
#include <sstream> 
#include <ios> 
#include <iomanip> 
#include <functional> 
#include <algorithm> 
#include <vector> 
#include <string> 
#include <list> 
#include <queue> 
#include <deque> 
#include <stack> 
#include <set> 
#include <map> 
#include <cstdio> 
#include <cstdlib> 
#include <cmath> 
#include <cstring> 
#include <climits> 
#include <cctype> 
#define INF 0x3f3f3f3f 
#define MP(X,Y) make_pair(X,Y) 
#define PB(X) push_back(X) 
#define REP(X,N) for(int X=0;X<N;X++) 
#define REP2(X,L,R) for(int X=L;X<=R;X++) 
#define DEP(X,R,L) for(int X=R;X>=L;X--) 
#define CLR(A,X) memset(A,X,sizeof(A)) 
#define IT iterator 
#define M_PI 3.14159265358979323846 
#define _ ios_base::sync_with_stdio(0);cin.tie(0); 
#define X first 
#define Y second 
#define MAX_V 10101 
#define maxn 10 
#define lowbit(X) (X & (-X)) 
#include<ctime> 
using namespace std; 
typedef long long ll; 
typedef pair<int,int>PII; 
typedef pair<PII,int>PPI; 
  
/************************************************
********************头文件**********************
************************************************/  
int G[101][101]; //G[i][j]表示i比j最少高G[i][j]
int T[101]; //T[i]表示i最少的分数
int P[101]; //过度T[]
int main() 
{ 
    int t; 
    cin>>t; 
    while(t--) 
    { 
        int n,p,q; 
        cin>>n>>p>>q; 
        memset(G,0,sizeof(G)); ///
        memset(T,0,sizeof(T)); /初始化
        memset(P,0,sizeof(P)); ///
          
        int a,b,x; 
        REP(i,p) 
        { 
            cin>>a>>x; 
            a--; 				//编号从0开始
            T[a] = x; 			//记录分数
        } 
        REP(i,q) 
        { 
            cin>>a>>b>>x; 
            a--;b--; 
            if(x>G[a][b]) //因为标明可能有多组数据就必然有多组数据
            G[a][b] = x; //始终保持取到较大的差值
        } 
        REP(i,min(n,q)) //取n,q中的小值就可以完成全部更新
        { 
            REP(j,n) 
            REP(k,n) //循环遍历每个条件
            { 
                int g; 
                g = G[j][k]; //g >0 题中已注明
                if(g != 0&&T[j]-T[k]<g) //将需要更新分数的进行记录,如果直接更新会出错
                { 
                    //cout<<j<<" "<<k<<" "<<T[j];  
                    if(P[j]<T[k]+g)P[j] = T[k] + g; 
                    //cout<<" "<<P[j]<<endl; 
                } 
                  
            } 
            REP(i,n) //将记录的分数更新
                { 
                    if(P[i] != 0) 
                        T[i] = P[i]; 
                      
                } 
            //cout<<endl;  
        } 
        cout<<T[0]<<endl; //输出第一个的分数
    } 
    return 0; 
} 


这道题目不算很难用这种方法时间复杂度能够满足要求。也可以用pair把几个条件编号,每次只需遍历q次就可以更新一遍数据。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值