北大ACM校内赛解题报告

今天去打酱油的。。。水了四道题,给各种IOI、ACM Final的大神跪。。。


B. Easy Task


根据给出的条件,不停地更新上界和下届即可,水题。

#include <iostream>
#include <stdlib.h>
#include <cassert>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <limits.h>
#include <utility>

using namespace std;

int main() {
    int t;
    cin>>t;
    for(int i=1; i<=t; i++) {
            int n;
            cin>>n;
            int upp = INT_MAX-10;
            int low = INT_MIN+10;
            int equal = -1;
            bool flag = false;
            for(int j=0; j<n; j++){
                    string s;
                    int cur;
                    cin>>s>>cur;
                    if(s == "=") { flag = true; }
                    else if(s == ">=") { low = max(low, cur); }
                    else if(s == ">") {low = max(low, cur+1); }
                    else if(s == "<=") {upp = min(upp, cur); }
                    else if(s == "<") {upp = min(upp, cur-1);}
            }
            if(flag){cout<<1<<endl;}
            else if(upp==INT_MAX-10 || low==INT_MIN+10){cout<<-1<<endl;}
            else{cout<<(upp-low+1)<<endl;}
    }
    return 0;
}


 
 

C. Robot

广度优先搜索的变种,关键问题在于要优化搜索的步骤,防止超时和超内存空间,比赛的时候一开始就超时超到死。。。

#include <iostream>
#include <stdlib.h>
#include <cassert>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <limits.h>
#include <utility>

using namespace std;

const int dir_x[] = {0, 0, -1, 1};
const int dir_y[] = {1, -1, 0, 0};
int main() {
    int t;
    cin>>t;
    while(t--){
               int row, col;
               cin>>row>>col;
               string g[4005];               
               int res = 0;
               for(int i=0; i<row; i++){ cin>>g[i]; }
               queue<pair<int, int> > A, B;               
               while(A.empty() == false) A.pop();
               while(B.empty() == false) B.pop();
               char prev = g[0][0];
               char cur = g[0][0];
               g[0][0] = 'Z';
               if(cur == 'A') A.push(make_pair(0, 0));
               else B.push(make_pair(0, 0));
               while(true){                      
                           if(cur == 'A'){
                                  if(A.empty()) break;
                                  while(A.empty()==false){
                                      pair<int, int> p = A.front();
                                      A.pop();
                                      int x = p.first; int y = p.second;
                                      for(int i=0; i<4; i++){
                                              int xx = x+dir_x[i];
                                              int yy = y+dir_y[i];
                                              if(xx>=row || xx<0 || yy>=col || yy<0) continue;
                                              if(g[xx][yy]=='Z' || g[xx][yy]=='.') continue;
                                              if(g[xx][yy]=='A'){
                                                    g[xx][yy] = 'Z';
                                                    A.push(make_pair(xx, yy));
                                                    continue;
                                              }
                                              else if(g[xx][yy]=='B'){
                                                   g[xx][yy] = 'Z';
                                                   B.push(make_pair(xx, yy));
                                                   continue;
                                              }
                                      }
                                  }
                                  res++;
                           }
                           else if(cur == 'B'){
                                  if(B.empty()) break;
                                  while(B.empty()==false){
                                      pair<int, int> p = B.front();
                                      B.pop();
                                      int x = p.first; int y = p.second;
                                      for(int i=0; i<4; i++){
                                              int xx = x+dir_x[i];
                                              int yy = y+dir_y[i];
                                              if(xx>=row || xx<0 || yy>=col || yy<0) continue;
                                              if(g[xx][yy]=='Z' || g[xx][yy]=='.') continue;
                                              if(g[xx][yy]=='B'){
                                                    g[xx][yy] = 'Z';
                                                    B.push(make_pair(xx, yy));
                                                    continue;
                                              }
                                              else if(g[xx][yy]=='A'){
                                                   g[xx][yy] = 'Z';
                                                   A.push(make_pair(xx, yy));
                                                   continue;
                                              }
                                      }
                                  }
                                  res++;
                           }
                           if(prev == 'A') {cur = 'B'; prev = 'B'; }
                           else if(prev == 'B') {cur = 'A'; prev = 'A';}
               }          
               cout<<res<<endl;               
    }
    return 0;
}

F. Balloon

首先要注意到数据范围很小,因此可以进行暴力搜索,为了提高搜索的效率,可以采用位运算来记录当前气球是否已经被击中,以及采用备忘录式的动态规划也有助于提高算法效率。

#include <iostream>
#include <stdlib.h>
#include <cassert>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <limits.h>
#include <utility>

using namespace std;
int n, t;
int x[15], y[15], z[15];
int score[15][5];
int dp[3000][5];
int res = 0;
bool flag = false;

bool check(int a1, int b1, int c1, int a2, int b2, int c2){
     double lam = 0;
     if(a2 != 0){ lam = ((double)a1)/a2; }
     else if(b2 != 0) {lam = ((double)b1)/b2; }
     else{ lam = ((double)c1)/c2; }
     if(fabs(a1-lam*a2) > 1e-6) return false;
     else if(fabs(b1-lam*b2) > 1e-6) return false;
     else if(fabs(c1-lam*c2) > 1e-6) return false;
     return true;
}

bool solve(int cur, int shoot) {
     if(cur==((1<<n)-1)){ flag = true; return true;}
     if(shoot>=t) return false;
     if(dp[cur][shoot]>0) return true;
     vector<int> v;
     v.clear();
     bool res = false;
     for(int i=0; i<n; i++){
             if(((1<<i)&cur) == 0) v.push_back(i);
     }
     int len = v.size();
     for(int i=0; i<len; i++){
             bool tt = solve(cur|(1<<v[i]), shoot+1);
             if(tt){
                 dp[cur][shoot] = max(dp[cur][shoot], dp[cur|(1<<v[i])][shoot+1]+score[v[i]][shoot] );
                 res = true;
             }
     } 
     int tmp = 0;    
     for(int i=0; i<len; i++)
     for(int j=i+1; j<len; j++){
             int st = cur|(1<<v[i]);
             st = st|(1<<v[j]);
             tmp = score[v[i]][shoot]+score[v[j]][shoot];
             int a1 = x[v[i]]-x[v[j]];
             int b1 = y[v[i]]-y[v[j]];
             int c1 = z[v[i]]-z[v[j]];
             for(int k=0; k<len; k++) {
                     if(k==i || k==j) continue;
                     int a2 = x[v[i]]-x[v[k]];
                     int b2 = y[v[i]]-y[v[k]];
                     int c2 = z[v[i]]-z[v[k]];
                     bool ok = check(a1, b1, c1, a2, b2, c2);
                     if(ok){ st = st|(1<<v[k]); tmp += score[v[k]][shoot]; }
             }
             bool tt = solve(st, shoot+1);
             if(tt){
               res = true;
               dp[cur][shoot] = max(dp[cur][shoot], tmp+dp[st][shoot+1]);
             }
     }
     return res;     
}

int main() {
    int c;
    cin>>c;
    while(c--) {         
         flag = false;
         cin>>n>>t;         
         for(int i=0; i<n; i++) cin>>x[i]>>y[i]>>z[i];
         for(int i=0; i<n; i++)
         for(int j=0; j<t; j++)
                 cin>>score[i][j];
         memset(dp, 0, sizeof(dp));
         res = 0;
         bool ok = solve(0, 0);               
         if(flag && ok)
            cout<<dp[0][0]<<endl;
         else cout<<-1<<endl;         
    }
    
    return 0;
}

H. Chemical Reaction

注意到数据规模较大,而b属性符号不同的元素不可能产生正能量,所以可考虑将b为正和b为负的两种情形分开来讨论,对于每一种情形,应该找到O(N)的算法,否则就很可能会超时,方法是采用两个指针分别在左右两侧扫描,和two sum问题挺像的。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <cassert>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <limits.h>
#include <utility>

using namespace std;

int main() {
    int c;
    cin>>c;    
    while(c--) {
               int n;
               scanf("%d", &n);
               long long res = -9999999999LL;
               if(n < 50){
                    vector<pair<long long, long long> > v;
                    v.clear();
                    for(int i=0; i<n; i++){
                            pair<long long, long long> p;
                            cin>>p.first>>p.second;
                            v.push_back(p);
                    }
                    for(int i=0; i<n; i++)
                    for(int j=i+1; j<n; j++){
                            long long tmp = (v[i].second*v[j].second)/(max(abs(v[i].second), abs(v[j].second)));
                            res = max(res, (long long)abs(v[i].first-v[j].first)*tmp);
                    }
                    cout<<res<<endl;
                    continue;
               }
               vector<pair<long long, long long> > pos, neg;
               pos.clear(); neg.clear();
               for(int i=0; i<n; i++){
                       pair<long long, long long> p;
                       cin>>p.first>>p.second;
                       //scanf("%d%d", &p.first, &p.second);
                       if(p.second < 0) neg.push_back(p);
                       else pos.push_back(p);
               }
               
               sort(pos.begin(), pos.end());
               sort(neg.begin(), neg.end());
               int len = neg.size();
               for(int i=0; i<len; i++) neg[i].second = -neg[i].second;
               
               int right = pos.size()-1;
               int left = 0;
               int ptr;
               while(right > left){
                           res = max(res, (long long)(pos[right].first-pos[left].first)*min(pos[right].second, pos[left].second));
                           if (pos[right].second < pos[left].second){
                           ptr = right-1;
                           while(ptr>left && pos[ptr].second<pos[right].second) ptr--;                           
                           right = ptr;
                           if(right <= left) break;             
                           
                           res = max(res, (long long)(pos[right].first-pos[left].first)*min(pos[right].second, pos[left].second));
                           }
                           else{
                           ptr = left+1;
                           while(ptr<right && pos[ptr].second<pos[left].second) ptr++;
                           left = ptr;
                           if(right <= left) break;
                           res = max(res, (long long)(pos[right].first-pos[left].first)*min(pos[right].second, pos[left].second));
                           }
               }
               
               right = neg.size()-1;
               left = 0;
               while(right > left){
                           res = max(res, (long long)(neg[right].first-neg[left].first)*min(neg[right].second, neg[left].second));
                           if (neg[right].second < neg[left].second){
                           ptr = right-1;
                           while(ptr>left && neg[ptr].second<neg[right].second) ptr--;
                           right = ptr;
                           if(right <= left) break;
                           res = max(res, (long long)(neg[right].first-neg[left].first)*min(neg[right].second, neg[left].second));
                           }
                           else{
                           ptr = left+1;
                           while(ptr<right && neg[ptr].second<neg[left].second) ptr++;
                           left = ptr;
                           if(right <= left) break;
                           res = max(res, (long long)(neg[right].first-neg[left].first)*min(neg[right].second, neg[left].second));
                           }
               }
               
               cout<<res<<endl;
    }
    return 0;
}

好像暴露我是哪所学校的了。。。渣渣啊。。。

你可能感兴趣的:(北大ACM校内赛解题报告)