USACO 2016 January Contest, Gold解题报告

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\n",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;
}

猜你喜欢

转载自www.cnblogs.com/wisdom-jie/p/9289682.html