1.Angry Cows
http://www.usaco.org/index.php?page=viewproblem2&cpid=597
dp题+vector数组运用
将从左向右与从右向左扫描结合。先从左到右DP,确定每个干草捆向右爆炸的最小半径,再从右到左,确定每个干草捆向左爆炸的最小半径。通过扫描每个干草捆,用这两个数字来确定我们应该设置初始引爆点的最佳位置。
#include <cstdio> #include <algorithm> #include <vector> using namespace std; #define INF 2000000000 int main() { //freopen("angry.in", "r", stdin); //freopen("angry.out", "w", stdout); int n; scanf("%d",&n); vector<int> a(n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); a[i]*=2; } sort(a.begin(), a.end()); a.resize(unique(a.begin(),a.end())-a.begin()); vector<int> DP[2]; for(int it=0;it<2;it++) { int l=0; DP[it].resize(n,INF); DP[it][0]=-2; for(int i=1;i<n;i++) { while(l+1<i&&abs(a[i]-a[l+1])>DP[it][l+1]+2) { l++; } DP[it][i]=min(abs(a[i]-a[l]),DP[it][l+1]+2); } reverse(a.begin(),a.end()); } reverse(DP[1].begin(),DP[1].end()); int i=0,j=n-1,res=INF; while(i<j) { res=min(res,max((a[j]-a[i])/2,2+max(DP[0][i],DP[1][j]))); if(DP[0][i+1]<DP[1][j-1]) i++; else j--; } printf("%d.%d ",res/2,(res%2?5:0)); return 0; }
2.Radio Contact
这个问题实际上是一个隐藏的 动态时间扭曲问题,其中误差函数是FJ和Bessie之间的平方距离。
因此,可以通过动态编程解决问题。对于Farmer John和Bessie的每个可能的位置,我们可以通过尝试向前迈出FJ,向前走Bessie,向前移动他们来计算他们达到最终位置所需的最小能量。
#include <vector> #include <cstring> #include <cstdio> #include <map> #include <iostream> using namespace std; #define INF 0x7FFFFFFFFFFFFFFFLL long long memo[1010][1010]; vector<pair<long long, long long> > F; vector<pair<long long, long long> > B; long long solve(int fi, int bi) { /* The energy cost of the radio for this timestep. */ long long base = (F[fi].first - B[bi].first) * (F[fi].first - B[bi].first) + (F[fi].second - B[bi].second) * (F[fi].second - B[bi].second); if (fi + 1 == F.size() && bi + 1 == B.size()) { return base; } long long& ref = memo[fi][bi]; if (ref != -1) return ref; /* Don't include the cost of the first timestep. */ if (fi == 0 && bi == 0) base = 0; ref = INF; if (fi + 1 < F.size()) { /* Step FJ forward. */ ref = min(ref, base + solve(fi + 1, bi)); } if (bi + 1 < B.size()) { /* Step Bessie forward. */ ref = min(ref, base + solve(fi, bi + 1)); } if (fi + 1 < F.size() && bi + 1 < B.size()) { /* Step both forward. */ ref = min(ref, base + solve(fi + 1, bi + 1)); } return ref; } int main() { //freopen("radio.in", "r", stdin); //freopen("radio.out", "w", stdout); map<char, int> dx, dy; dx['E'] = 1; dx['W'] = -1; dy['N'] = 1; dy['S'] = -1; int N, M; scanf("%d%d",&N,&M); int fx, fy, bx, by; scanf("%d%d%d%d",&fx,&fy,&bx,&by); string SF, SB; cin >> SF >> SB; /* Compute FJ's path. */ F.push_back(make_pair(fx, fy)); for (int i = 0; i < SF.size(); i++) { fx += dx[SF[i]]; fy += dy[SF[i]]; F.push_back(make_pair(fx, fy)); } /* Compute Bessie's path. */ B.push_back(make_pair(bx, by)); for (int i = 0; i < SB.size(); i++) { bx += dx[SB[i]]; by += dy[SB[i]]; B.push_back(make_pair(bx, by)); } memset(memo, -1, sizeof(memo)); cout << solve(0, 0) << endl; return 0; }