BNU Training 2015.08.17

        题目链接

        这套题目比较简单,为了庆祝为数不多的AK,决定把题解发一下。233....

        A. Smooth Visualization(UVALive 5870 Smooth Visualization)

        签到题一个,搞搞搞就行了。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 10000;

char ans[10][maxn];
char ch[maxn];

void solve()
{
    int len = strlen(ch);
    int cnt = ch[0] - '0';
    cnt = 7 - cnt;
    int q = ch[0] - '0';
    for(int i = 0; i < 7; i ++)
    {
        if(cnt)
        {
            ans[i][0] = '*'; cnt --;
        }
        else ans[i][0] = '+';
    }
    int n = 1;
    for(int i = 1; i < len; i ++)
    {
        q = max(q, ch[i] - '0');
        int tmp = ch[i] - ch[i - 1];
        if(abs(tmp) <= 1)
        {
            cnt = 7 - (ch[i] - '0');
            for(int j = 0; j < 7; j ++)
            {
                if(cnt)
                {
                    ans[j][n] = '*'; cnt --;
                }
                else ans[j][n] = '+';
            }
            n ++;
        }
        else if(tmp > 0)
        {
            ch[i - 1] ++;
            cnt = 7 - (ch[i - 1] - '0');
            for(int j = 0; j < 7; j ++)
            {
                if(cnt)
                {
                    ans[j][n] = '*'; cnt --;
                }
                else ans[j][n] = '+';
            }
            n ++; i --;
        }
        else
        {
            ch[i - 1] --;
            cnt = 7 - (ch[i - 1] - '0');
            for(int j = 0; j < 7; j ++)
            {
                if(cnt)
                {
                    ans[j][n] = '*'; cnt --;
                }
                else ans[j][n] = '+';
            }
            n ++;  i --;
        }
    }
    for(int i = 0; i < 7; i ++)
        ans[i][n] = 0;
    for(int i = 7 - q; i < 7; i ++)
        puts(ans[i]);
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%s", ch);
        solve();
    }
    return 0;
}
         B. Arnooks's Defensive Line(UVALive 5871 Arnooks's Defensive Line )

         因为看起来是单组数据,n=500000,cdq分治的话,算了下时间复杂度正好。于是就是一道cdq分治裸题。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 500100;

struct Node
{
    char op;
    int l, r, id;
    void in(int i)
    {
        char ch[2];
        scanf("%s%d%d", ch, &l, &r);
        op = ch[0]; id = i;
    }
    bool operator < (const Node& rhs) const
    {
        return l < rhs.l;
    }
}a[maxn];

int C[maxn];

void add(int x, int ad)
{
    while(x < maxn)
    {
        C[x] += ad;
        x += x & (-x);
    }
}

int sum(int x)
{
    int ret = 0;
    while(x)
    {
        ret += C[x];
        x -= x & (-x);
    }
    return ret;
}

int n;
vector<int> vec;
int ans[maxn];

void divide(int l, int r)
{
    if(l == r) return ;
    int m = (l + r) >> 1;
    divide(l, m);
    divide(m + 1, r);
    sort(a + l, a + m + 1);
    sort(a + m + 1, a + r + 1);
    int cnt = 0;
    for(int i = m + 1, j = l; i <= r; i ++)
    {
        while(j <= m && a[j].l <= a[i].l)
        {
            if(a[j].op != '?') add(a[j].r, 1), cnt ++;
            j ++;
        }
        if(a[i].op == '?')
        {
            if(ans[a[i].id] == -1) ans[a[i].id] = 0;
            ans[a[i].id] += cnt - sum(a[i].r - 1);
        }
    }
    for(int i = m + 1, j = l; i <= r; i ++)
    {
        while(j <= m && a[j].l <= a[i].l)
        {
            if(a[j].op != '?') add(a[j].r, -1);
            j ++;
        }
    }
}

void solve()
{
    vec.clear();
    for(int i = 1; i <= n; i ++)
    {
        vec.push_back(a[i].r);
    }
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
    for(int i = 1; i <= n; i ++)
    {
        a[i].r = lower_bound(vec.begin(), vec.end(), a[i].r) - vec.begin() + 1;
    }
    CLR(C, 0);
    CLR(ans, -1);
    divide(1, n);
    for(int i = 1; i <= n; i ++)
        if(ans[i] != -1) printf("%d\n", ans[i]);
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++)
        a[i].in(i);
    solve();
    return 0;
}
        C. Equivalence(UVALive 5872 Equivalence )
        这题随便模拟就好了。做的时候uvalive崩掉了,于是连交了十来发。。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define INF 1200000000000000000ll
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;

map<string,LL> mp;
map<string,LL> ::iterator it;

struct Exp{
    vector<string> _exp;
    vector<LL> xishu;
    char tmp[100];
    void init(){
        _exp.clear();
        xishu.clear();
    }
    void hebing(){
        mp.clear();
        for(int i=0;i<_exp.size();i++){
            sort(_exp[i].begin(),_exp[i].end());
            mp[_exp[i]]+=xishu[i];
        }
        init();
        for(it=mp.begin();it!=mp.end();++it){
            if(it->yy!=0) _exp.push_back(it->xx),xishu.push_back(it->yy);
        }
    }
};

Exp add(Exp a,Exp b){
    Exp ans;ans=b;
    for(int i=0;i<a._exp.size();i++){
        ans._exp.push_back(a._exp[i]);
        ans.xishu.push_back(a.xishu[i]);
    }
    ans.hebing();
    return ans;
}

Exp sub(Exp a,Exp b){
    Exp ans;ans=a;
    for(int i=0;i<b._exp.size();i++){
        ans._exp.push_back(b._exp[i]);
        ans.xishu.push_back(-b.xishu[i]);
    }
    ans.hebing();
    return ans;
}

Exp mult(Exp a,Exp b){
    Exp ans;ans.init();
    for(int i=0;i<a._exp.size();i++){
        for(int j=0;j<b._exp.size();j++){
            string tmp=a._exp[i];
            if(tmp == "1") tmp = b._exp[j];
            else if(b._exp[j] != "1") tmp=tmp+b._exp[j];
            ans._exp.push_back(tmp);
            ans.xishu.push_back(a.xishu[i]*b.xishu[j]);
        }
    }
    ans.hebing();
    return ans;
}

string a, b;

Exp dfs(int l, int r)
{
    Exp ret; ret.init();
    if(l == r)
    {
        if(a[l] >= '0' && a[l] <= '9')
        {
            ret._exp.push_back("1");
            ret.xishu.push_back(a[l] - '0');
        }
        else
        {
            string str = "";
            str += a[l];
            ret._exp.push_back(str);
            ret.xishu.push_back(1);
        }
        return ret;
    }
    vector<Exp> vec;
    string str = "";
    for(int i = l; i <= r; i ++)
    {
        Exp tmp;
        if(a[i] == '(')
        {
            int j = i + 1, cnt = 1;
            while(j <= r)
            {
                if(a[j] == '(') cnt ++;
                else if(a[j] == ')') cnt --;
                if(cnt == 0) break;
                j ++;
            }
            tmp = dfs(i + 1, j - 1);
            i = j;
        }
        else
        {
            tmp = dfs(i, i);
        }
        i ++;
        if(i <= r) str += a[i];
        vec.push_back(tmp);
    }
    Exp tmp; tmp.init();
    for(int i = 0; i < vec.size(); i ++)
    {
        tmp = vec[i];
        int j = i;
        while(i < str.size() && str[i] == '*')
        {
            tmp = mult(tmp, vec[i + 1]);
            i ++;
        }
        if(j)
        {
            if(str[j - 1] == '+') ret = add(ret, tmp);
            else
            {
                ret = sub(ret, tmp);
            }
        }
        else ret = tmp;
    }
    return ret;
}

char ch1[10010], ch2[10010];
void solve()
{
    gets(ch1);
    gets(ch2);
    int len = strlen(ch1);
    a = "(";
    for(int i = 0; i < len; i ++)
    {
        if(ch1[i] == ' ' || ch1[i] == '\t') continue;
        a += ch1[i];
    }
    a += ")";
    b = "";
    int len2 = strlen(ch2);
    for(int i = 0; i < len2; i ++)
    {
        if(ch2[i] == ' ' || ch2[i] == '\t') continue;
        b += ch2[i];
    }
    a += "-(";
    a += b;
    a += ")";
    for(int i = 0; i < a.size(); i ++)
    {
        if(a[i] >= 'A' && a[i] <= 'Z')
        {
            a[i] = a[i] - 'A' + 'a';
        }
    }
    Exp ret = dfs(0, a.size() - 1);
    if(ret._exp.size() == 0) puts("YES");
    else puts("NO");
}

int main(){
    int T;
    scanf("%d", &T);
    getchar();
    while(T --)
    {
        solve();
    }
    return 0;
}

        D. Tree Inspections (UVALive 5873 Tree Inspections )

        这题题意是给你n个点,然后m个横线或者竖线,如果满足在直线上站着,能垂直看到60%以上的点的话,就输出PASSED。

        横线和竖线情况相同,对于一个横线,只需要考虑他和相邻横线之间的看见的情况就可以了。可以分向上看和向下看两种情况。然后模拟一下就行了。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;

const int maxn = 100100;

struct Point
{
    int x, y, id;
    void inpt(int i)
    {
        scanf("%d%d", &x, &y);
        id = i;
    }
}p[maxn];

bool cmp1(Point a, Point b)
{
    return a.x < b.x;
}

bool cmp2(Point a, Point b)
{
    return a.y < b.y;
}

vector<int> H, V;

bool vis[maxn];

void solve()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i ++)
        p[i].inpt(i);
    H.clear(); V.clear();
    for(int i = 0; i < m; i ++)
    {
        char op[2]; int x;
        scanf("%s%d", op, &x);
        if(op[0] == 'H') H.push_back(x);
        else V.push_back(x);
    }
    CLR(vis, false);
    sort(H.begin(), H.end());
    sort(V.begin(), V.end());
    sort(p, p + n, cmp1);
    map<int, int> mp;
    for(int i = 0, j = 0; i < H.size(); i ++)
    {
        int h = H[i];
        mp.clear();
        while(j < n && p[j].x <= h)
        {
            if(mp.count(p[j].y))
            {
                if(p[mp[p[j].y]].x > p[j].x)
                {
                    mp[p[j].y] = j;
                }
            }
            else mp[p[j].y] = j;
            j ++;
        }
        map<int, int>::iterator it;
        for(it = mp.begin(); it != mp.end(); it ++)
        {
            vis[p[it->yy].id] = true;
        }
    }

    for(int i = 0, j = n - 1; i < H.size(); i ++)
    {
        int h = H[i];
        mp.clear();
        while(j >= 0 && p[j].x >= h)
        {
            if(mp.count(p[j].y))
            {
                if(p[mp[p[j].y]].x < p[j].x)
                {
                    mp[p[j].y] = j;
                }
            }
            else mp[p[j].y] = j;
            j --;
        }
        map<int, int>::iterator it;
        for(it = mp.begin(); it != mp.end(); it ++)
        {
            vis[p[it->yy].id] = true;
        }
    }

    sort(p, p + n, cmp2);

    for(int i = 0, j = 0; i < V.size(); i ++)
    {
        int v = V[i];
        mp.clear();
        while(j < n && p[j].y <= v)
        {
            if(mp.count(p[j].x))
            {
                if(p[mp[p[j].y]].y > p[j].y)
                {
                    mp[p[j].x] = j;
                }
            }
            else mp[p[j].x] = j;
            j ++;
        }
        map<int, int>::iterator it;
        for(it = mp.begin(); it != mp.end(); it ++)
        {
            vis[p[it->yy].id] = true;
        }
    }

    for(int i = 0, j = n - 1; i < V.size(); i ++)
    {
        int v = V[i];
        mp.clear();
        while(j >= 0 && p[j].y >= v)
        {
            if(mp.count(p[j].x))
            {
                if(p[mp[p[j].y]].y < p[j].y)
                {
                    mp[p[j].x] = j;
                }
            }
            else mp[p[j].x] = j;
            j --;
        }
        map<int, int>::iterator it;
        for(it = mp.begin(); it != mp.end(); it ++)
        {
            vis[p[it->yy].id] = true;
        }
    }
    int ans = 0;
    for(int i = 0; i < n; i ++)
        if(vis[i]) ans ++;//, printf("%d -- %d\n", p[i].x, p[i].y);
    if(ans * 10 >= n * 6) puts("PASSED");
    else puts("FAILED");
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        solve();
    }
    return 0;
}

       E. Social Holidaying(UVALive 5874 Social Holidaying)

       这题直接最大匹配就过了。可以的就连双向边,然后最大匹配除以二

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn=1000;

int a[maxn],b[maxn];

struct BPM
{
  int n, m;               // 左右顶点个数
  vector<int> G[maxn];      // 邻接表
  int left[maxn];         // left[i]为右边第i个点的匹配点编号,-1表示不存在
  bool T[maxn];           // T[i]为右边第i个点是否已标记

  void init(int n, int m) {
    this->n = n;
    this->m = m;
    for(int i=0;i<=n;i++) G[i].clear();
  }

  bool match(int u){
    for(int i = 0;i < G[u].size(); i++) {
        int v=G[u][i];
        if(!T[v]) {
          T[v] = true;
          if (left[v] == -1 || match(left[v])){
            left[v] = u;
            return true;
          }
        }
    }
    return false;
  }
  // 求最大匹配
  int solve() {
    memset(left, -1, sizeof(left));
    int ans = 0;
    for(int u = 0; u < n; u++) {
      memset(T, 0, sizeof(T));
      if(match(u)) ans++;
    }
    return ans;
  }
}sol;

set<int> _hash;

int main(){
    int t;scanf("%d",&t);
    while(t--){
        int n,m;scanf("%d%d",&n,&m);
        _hash.clear();
        for(int i=0;i<n;i++) scanf("%d",&a[i]);
        for(int i=0;i<m;i++){
            scanf("%d",&b[i]);
            _hash.insert(b[i]);
        }
        sol.init(n,n);
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++) if(i!=j){
                if(_hash.find(a[i]+a[j])!=_hash.end()){
                    sol.G[i].push_back(j);
                    sol.G[j].push_back(i);
                }
            }
        }
        printf("%d\n",sol.solve()/2);
    }
    return 0;
}

       F. Orienteering(UVALive 5875 Orienteering)
       这题发现不能背包距离,但是可以背包分数呀!于是愉快的背包出所有分数的最短距离。然后每个询问查一下就行了。查的时候随便查,二分什么的都行。暴力也能过。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 60600;
#define MOD 1000000009

double eps = 1e-8;

double dp[33][maxn];

double sqr(double x){
    return x*x;
}

int sign(double x){
    return (x>eps)-(x<-eps);
}

struct Point
{
    double x, y;
    int s;
    void inpt()
    {
        scanf("%lf%lf%d", &x, &y, &s);
    }
}p[40];

double dist(Point a,Point b){
    return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}

int Max[40];

double dis[40][40];
double ans[maxn];
int n;

void solve()
{
    for(int i = 1; i <= n; i ++)
        p[i].inpt();
    p[0].x = 0; p[0].y = 0; p[0].s = 0;
    for(int i = 0; i <= n; i ++)
    {
        for(int j = 0; j <= n; j ++)
            dis[i][j] = dist(p[i], p[j]);
    }
    for(int i = 0; i <= n; i ++)
    {
        for(int j = 0; j < maxn; j ++)
            dp[i][j] = 1e30;
    }
    dp[0][0] = 0;
    Max[0] = 0;
    for(int i = 1; i <= n; i ++)
    {
        Max[i] = 0;
        for(int j = 0; j < i; j ++)
        {
            for(int k = 0; k <= Max[j]; k ++)
            {
                dp[i][k + p[i].s] = min(dp[i][k + p[i].s], dp[j][k] + dis[i][j] - dis[j][0] + dis[i][0]);
            }
            Max[i] = max(Max[i], Max[j] + p[i].s);
        }
    }
    for(int i = 0; i < maxn; i ++)
        ans[i] = 1e20;
    int tot = 0;
    for(int i = 0; i <= n; i ++)
    {
        tot = max(tot, Max[i]);
        for(int j = 0; j <= Max[i]; j ++)
        {
            ans[j] = min(ans[j], dp[i][j]);
        }
    }
    char ch[100]; double d;
    while(scanf("%s%lf", ch, &d), ch[0] != '#')
    {
        int out = -1;
        for(int i = 0; i <= tot; i ++)
        {
            if(sign(d - ans[i]) >= 0)
            {
                out = i;
            }
        }
        printf("%s: %d\n", ch, out);
    }
}

int main()
{
    int T, cas = 1;
    while(scanf("%d", &n), n)
    {
        printf("Race %d\n", cas ++);
        solve();
    }
}
        G. Writings on the Wall(UVALive 5876 Writings on the Wall)

        求两个串可重叠的相连有多少种情况,扩展kmp裸题。。当s后缀和t公共前缀等于s后缀长度的时候,就是可以拼接的时候。然后。。ans++

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define INF 1200000000000000000ll
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 100100;
#define MOD 1000000007

const int N = 101010;
int next[N],extand[N];
void getnext(char *T) // next[i]: 以第i位置开始的子串 与 T的公共前缀
{
    int i,length = strlen(T);
    next[0] = length;
    for(i = 0; i<length-1 && T[i]==T[i+1]; i++);
    next[1] = i;
    int a = 1;
    for(int k = 2; k < length; k++)
    {
        int p = a+next[a]-1, L = next[k-a];
        if( (k-1)+L >= p )
        {
            int j = (p-k+1)>0? (p-k+1) : 0;
            while(k+j<length && T[k+j]==T[j]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较
            next[k] = j, a = k;
        }
        else next[k] = L;
    }
}
void getextand(char *S,char *T)
{
    memset(next,0,sizeof(next));
    getnext(T);
    int Slen = strlen(S), Tlen = strlen(T), a = 0;
    int MinLen = Slen>Tlen?Tlen:Slen;
    while(a<MinLen && S[a]==T[a]) a++;
    extand[0] = a, a = 0;
    for(int k = 1; k < Slen; k++)
    {
        int p = a+extand[a]-1, L = next[k-a];
        if( (k-1)+L >= p )
        {
            int j = (p-k+1)>0? (p-k+1) : 0;
            while(k+j<Slen && j<Tlen && S[k+j]==T[j] ) j++;
            extand[k] = j;
            a = k;
        }
        else extand[k] = L;
    }
}

char s[N],t[N];

void solve()
{
    scanf("%s%s",s,t);
    getextand(s,t);
    int ans = 1;
    int len = strlen(s);
    for(int i = 0; i < len; i++)
    {
        if(len - i == extand[i]) ans ++;
    }
    printf("%d\n", ans);
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --) solve();
    return 0;
}

       H. Robotic Traceur(UVALive 5877 Robotic Traceur)
       就是最小步数的最短路,并没有发现什么坑。。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define LL long long
#define MP make_pair
#define xx first
#define yy second
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))
using namespace std;

const double eps=1e-8;

double sqr(double x)
{
    return x*x;
}

int sign(double x)
{
    return (x>eps)-(x<-eps);
}

const int maxn = 1010;

struct Point
{
    double x,y;
    Point(double _x=0,double  _y=0)
    {
        x=_x,y=_y;
    }
    void input()
    {
        scanf("%lf%lf",&x,&y);
    }
} p[1024];

double dist(Point a,Point b){
    return sqr(a.x-b.x)+sqr(a.y-b.y);
}

vector<int> G[maxn];
bool vis[maxn];
int dp[maxn];

int gao(int s, int t)
{
    queue<int> Q;
    Q.push(s);
    CLR(vis, false);
    CLR(dp, INF);
    dp[s] = 0;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        vis[u] = false;
        for(int i = 0; i < G[u].size(); i ++)
        {
            int v = G[u][i];
            if(dp[v] > dp[u] + 1)
            {
                dp[v] = dp[u] + 1;
                if(!vis[v]) Q.push(v);
                vis[v] = true;
            }
        }
    }
    return dp[t];
}

void solve()
{
    int n, s, t;
    double l1, l2;
    scanf("%d%d%d%lf%lf", &n, &s, &t, &l1, &l2);
    l1 += l2;
    for(int i = 1; i <= n; i ++)
        p[i].input(), G[i].clear();
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 1; j <= n; j ++) if(i != j)
        {
            if(sign(dist(p[i], p[j]) - sqr(l1)) <= 0)
            {
                G[i].push_back(j);
            }
        }
    }
    int ret = gao(s, t);
    if(ret == INF) puts("Impossible");
    else printf("%d\n", ret);
}
        I. Shortest Leash(UVALive 5878 Shortest Leash)

        其实我发这篇文的目的,就是说一下这道题。。

        这道题上来就被秒了,然而我感觉这道题很神啊!赛后发现大家都是用黑科技过的。。怪不得过了那么多。。个人感觉我们的思路是“杠杠的”正确。

        最后的答案,肯定是2^n种情况求出的点后排的凸包上的点。然后,假如我们已经用了前i个向量,而且求出了相应的凸包,那么,考虑第i+1个向量对当前的凸包的影响,就是把当前凸包向着i+1这个向量的两个方向拉伸了一些长度,稍微想象一下可以知道,这样的拉伸最多增加两个点啊!!于是,每次增加向量最多增加两个点。。于是,按顺序添加向量,维护凸包就可以了。。。

        加向量,排凸包,加向量,排凸包。。复杂度O(n^2*log(n))。

#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const double inf=1e10;
const double eps=1e-8;

double sqr(double x){
    return x*x;
}

int sign(double x){
    return (x>eps)-(x<-eps);
}

struct Point{
    double x,y;
    Point(double _x=0,double  _y=0){
        x=_x,y=_y;
    }
    Point operator+(const Point &a){
        return Point(x+a.x,y+a.y);
    }
    Point operator-(const Point &a){
        return Point(x-a.x,y-a.y);
    }
    void input(){
        scanf("%lf%lf",&x,&y);
    }
}p[1024],v[1024],res[1024];

double mult(Point sp,Point ep,Point op){
    return (sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y);
}
bool operator<(const Point &l,const Point &r){
    return l.y<r.y||(l.y==r.y&&l.x<r.x);
}
int graham(Point pnt[],int n,Point res[]){
    int i,len,k=0,top=1;
    sort(pnt,pnt+n);
    if(n==0) return 0;res[0]=pnt[0];
    if(n==1) return 1;res[1]=pnt[1];
    if(n==2) return 2;res[2]=pnt[2];
    for(i=2;i<n;i++){
        while(top&&mult(pnt[i],res[top],res[top-1])>=0) top--;
        res[++top]=pnt[i];
    }
    len=top;res[++top]=pnt[n-2];
    for(i=n-3;i>=0;i--){
        while(top!=len&&mult(pnt[i],res[top],res[top-1])>=0) top--;
        res[++top]=pnt[i];
    }
    return top;
}

double dist(Point a,Point b){
    return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}

int main(){
    int n;
    while(scanf("%d",&n),n){
        p[0]=Point(0,0);
        int m=1;
        double ans=-inf;
        for(int i=0;i<n;i++){
            Point tp;tp.input();
            int l=0;
            for(int j=0;j<m;j++){
                p[m+l]=p[j]+tp;l++;
                p[m+l]=p[j]-tp;l++;
            }
            m=graham(p,m+l,res);
            for(int j=0;j<m;j++) p[j]=res[j];
            for(int j=0;j<m;j++) ans=max(ans,dist(res[j],Point(0,0)));
        }
        printf("%.3f\n",ans);
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值