250pt:
给一幅图的每个点都赋值,使得相邻两个点的权值之差不超过d,最后问最大权与最小权之差是多少。
显然,任意两个点的差距不会超过他们的最短距离 * d。
500pt:
一个诡异的DP,需要枚举D,然后如果要凸显这个D是上界,必须要至少取一个D+1,而且要在非found类里面,因为D+1肯定不能再found类里面。枚举D后每次用dp统计就好了
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <sstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
template <class T> void checkmax(T &t, T x) { if (x > t) t = x; }
template <class T> void checkmin(T &t, T x) { if (x < t) t = x; }
template <class T> void _checkmax(T &t, T x) { if (t == -1 || x > t) t = x; }
template <class T> void _checkmin(T &t, T x) { if (t == -1 || x < t) t = x; }
typedef long long ll;
class Excavations {
public:
long long count(vector <int> kind, vector <int> depth, vector <int> found, int K) ;
};
const int N = 55;
ll dp[2][N],C[N][N];;
long long Excavations::count(vector <int> kind, vector <int> depth, vector <int> found, int K) {
REP(i,0,50) {
C[i][0] = 1;
REP(j,1,i) {
C[i][j] = C[i-1][j] + C[i-1][j-1];
}
}
//cout<<C[10][10]<<endl;
int n = kind.size() , m = found.size();
map<int,int> mp;
rep(i,n) mp[depth[i]]=0;
int D=0;
for(map<int,int>::iterator it = mp.begin(); it!=mp.end(); it++) it->second=D++;
rep(i,n) depth[i]=mp[depth[i]];
int cnt[55];
ll ans = 0;
rep(d,D) {
memset(cnt,0,sizeof(cnt));
int Higher = 0;
rep(i,n) {
int k = -1;
rep(j,m) if(found[j] == kind[i]) k = j;
if(depth[i] <= d && k !=-1) ++cnt[k];
else if(depth[i] == d+1 && k == -1) ++cnt[m]; // 非found类而且刚好大于d,来凸显d这个上界
else if(depth[i] > d)Higher ++;
}
// rep(i,m+1) cout<<cnt[i]<<" ";
// cout<<endl;
int cur = 0;
memset(dp[cur],0,sizeof(dp[cur]));
dp[0][0] = 1;
//cnt[0~m] 每一种至少选一个
rep(i,m+1) {
cur ^= 1;
memset(dp[cur],0,sizeof(dp[cur]));
REP(j,1,cnt[i]) {
REP(k,0,K-j) {
dp[cur][k+j] += dp[1-cur][k] * C[cnt[i]][j];
}
}
if(d == D-1 && i == m-1) ans += dp[cur][K];
}
// rep(i,K+1) cout<<dp[cur][i]<<" ";
// cout<<endl;
REP(i,0,K) ans += dp[cur][i] * C[Higher][K-i];
// cout<<"high:" <<Higher<<" "<<ans<<endl;
}
return ans;
}
// BEGIN CUT HERE
int main() {
Excavations ___test;
___test.run_test(-1);
}
// END CUT HERE
900pt:
两种做法,一种是用斯坦纳树,一种是用最小树形图