<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次就可以更新一遍数据。