斌神群之【清明节群赛】

下午的群赛题解由fjnu提供:

A题
题目给出一个一元一次方程,求解未知数。
这题直接模拟,分别求等号左边和右边未知数的系数和以及常数的和。
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<ctype.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const int MOD=1000000007;
char str[110000];
int main(){
    int T;
    scanf("%d", &T);
    while (T--){
        scanf("%s", str);
        int len = strlen(str);
        int ans1 = 0, ans2 = 0;
        int i = 0;
        bool flag = true;
        int mid = 0;
        char c;
        while (str[i] != '='){
            mid = 0;
            if (str[i] == '-'){
                flag = false;
                i++;
            }
            while (isdigit(str[i])){
                mid = mid * 10 + str[i] - 48;
                i++;
            }
            if (str[i] != '+'&&str[i] != '-'&&str[i] != '='){
                c = str[i];
                if (flag){
                    if (mid == 0) ans1++;
                    else ans1 += mid;
                }
                else{
                    if (mid == 0) ans1--;
                    else ans1 -= mid;
                }
                i++;
            }
            else{
                if (flag) ans2 += mid;
                else ans2 -= mid;
            }
            flag = true;
            if (str[i] == '+')
                i++;
        }
        i++;
        while (str[i]){
            mid = 0;
            if (str[i] == '-'){
                flag = false;
                i++;
            }
            while (isdigit(str[i])){
                mid = mid * 10 + str[i] - 48;
                i++;
            }
            if (str[i] != '+'&&str[i] != '-'&&str[i]){
                c = str[i];
                if (flag){
                    if (mid == 0) ans1--;
                    else ans1 -= mid;
                }
                else{
                    if (mid == 0) ans1++;
                    else ans1 += mid;
                }
                i++;
            }
            else{
                if (flag) ans2 -= mid;
                else ans2 +=mid;
            }
            flag = true;
            if (str[i] == '+')
                i++;
        }
        double s = floor(((-ans2)/(ans1*1.0)) * 1000 + 0.5) / 1000;
        printf("%c=%.3lf\n", c,s);
    }
}




B题
dp,题目要在原数中分插入N个乘号,那么就是将原数分成N+1部分进行相乘。那么这样设置状态dp[i][j],表示前j个位置分成i份得到的最大乘积。
考虑到数的最大长度40,超longlong,于是用高精度存。
状态方程:dp[i][j]=dp[i-1][k]+sum[k+1][j];其中sum[k+1][j]表示位置k+1到j对应的数字,sum直接暴力预处理就好了。


#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const int MOD=1000000007;
const int maxn=5100;
const int maxm=21000;
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
class BigNum
{
private:
    int a[500];
    int len;
public:
    BigNum(){ len = 1;memset(a,0,sizeof(a)); }
    BigNum(const int);
    BigNum(const char*);
    BigNum(const BigNum &);
    BigNum &operator=(const BigNum &);
 
    BigNum operator+(const BigNum &) const;
    BigNum operator-(const BigNum &) const;
    BigNum operator*(const BigNum &) const;
 
    bool   operator>(const BigNum & T)const;
    bool   operator>(const int & t)const;
 
    void print();
};
BigNum::BigNum(const int b)
{
    int c,d = b;
    len = 0;
    memset(a,0,sizeof(a));
    while(d > MAXN)
    {
        c = d - (d / (MAXN + 1)) * (MAXN + 1);
        d = d / (MAXN + 1);
        a[len++] = c;
    }
    a[len++] = d;
}
BigNum::BigNum(const char*s)
{
    int t,k,index,l,i;
    memset(a,0,sizeof(a));
    l=strlen(s);
    len=l/DLEN;
    if(l%DLEN)
        len++;
    index=0;
    for(i=l-1;i>=0;i-=DLEN)
    {
        t=0;
        k=i-DLEN+1;
        if(k<0)
            k=0;
        for(int j=k;j<=i;j++)
            t=t*10+s[j]-'0';
        a[index++]=t;
    }
}
BigNum::BigNum(const BigNum & T) : len(T.len)
{
    int i;
    memset(a,0,sizeof(a));
    for(i = 0 ; i < len ; i++)
        a[i] = T.a[i];
}
 
BigNum & BigNum::operator=(const BigNum & n)
{
    int i;
    len = n.len;
    memset(a,0,sizeof(a));
    for(i = 0 ; i < len ; i++)
        a[i] = n.a[i];
    return *this;
}
 
BigNum BigNum::operator+(const BigNum & T) const
{
    BigNum t(*this);
    int i,big;
    big = T.len > len ? T.len : len;
    for(i = 0 ; i < big ; i++)
    {
        t.a[i] +=T.a[i];
        if(t.a[i] > MAXN)
        {
            t.a[i + 1]++;
            t.a[i] -=MAXN+1;
        }
    }
    if(t.a[big] != 0)
        t.len = big + 1;
    else
        t.len = big;
    return t;
}
 
BigNum BigNum::operator*(const BigNum & T) const
{
    BigNum ret;
    int i,j,up;
    int temp,temp1;
    for(i = 0 ; i < len ; i++)
    {
        up = 0;
        for(j = 0 ; j < T.len ; j++)
        {
            temp = a[i] * T.a[j] + ret.a[i + j] + up;
            if(temp > MAXN)
            {
                temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
                up = temp / (MAXN + 1);
                ret.a[i + j] = temp1;
            }
            else
            {
                up = 0;
                ret.a[i + j] = temp;
            }
        }
        if(up != 0)
            ret.a[i + j] = up;
    }
    ret.len = i + j;
    while(ret.a[ret.len - 1] == 0 && ret.len > 1)
        ret.len--;
    return ret;
}
 
bool BigNum::operator>(const BigNum & T) const
{
    int ln;
    if(len > T.len)
        return true;
    else if(len == T.len)
    {
        ln = len - 1;
        while(a[ln] == T.a[ln] && ln >= 0)
            ln--;
        if(ln >= 0 && a[ln] > T.a[ln])
            return true;
        else
            return false;
    }
    else
        return false;
}
bool BigNum::operator >(const int & t) const
{
    BigNum b(t);
    return *this>b;
}
 
void BigNum::print()
{
    int i;
    cout << a[len - 1];
    for(i = len - 2 ; i >= 0 ; i--)
    {
        cout.width(DLEN);
        cout.fill('0');
        cout << a[i];
    }
    cout << endl;
};
BigNum dp[50][50],sum[50][50];
char str[50],temp[50];
 
int main(){
    //freopen("E:\\read.txt","r",stdin);
    int T,N;
    while(scanf("%d %d",&T,&N)!=EOF){
        scanf("%s",str+1);
        int len=strlen(str+1);
        for(int i=1;i<=len;i++){
            for(int j=i;j<=len;j++){
                int l=0;
                for(int k=i;k<=j;k++){
                    temp[l++]=str[k];
                }
                temp[l]='\0';
                sum[i][j]=temp;
            }
        }
        for(int i=0;i<50;i++)
            for(int j=0;j<10;j++)
                dp[i][j]=0;
        N++;
        for(int i=1;i<=T;i++)
            dp[1][i]=sum[1][i];
        for(int i=2;i<=N;i++){
            for(int j=i;j<=T;j++){
                for(int k=i-1;k<j;k++){
                    BigNum te=dp[i-1][k]*sum[k+1][j];
                    if(te>dp[i][j])
                        dp[i][j]=te;
                }
            }
        }
        dp[N][T].print();
    }
    return 0;
}






C题
这题也是dp。
题目要求输出能连接成的最长串长度,并非一定要全部连接,尽量长就好。如果两个串之间没有公共部分不能连接。
这题看下单词个数n<=20,然而单词的连接有需要排列组合,那么考虑用状压dp;
dp[s][i]表示状态为s,以第i个字符串为结尾对应的能连接的最长串。s是单词编号的集合。
那么状态返程:dp[s|(1<<j)][j]={ dp[s][i] + len[j] - dis[i][j] };
其中len[j]表示编号为j对应单词的长度,dis[i][j]表示字符串i和字符串j合并的公共部分。
dis[i][j]可以用通过暴力预处理出来,枚举任意两个串的任意位置进行拼接。
注意一点,题目要求从某个字符为开头的单词开始,初始状态就是找出以所给字母为开头的单词,可能不止一个。


#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const int MOD=1000000007;
char str[22][1000005];
int dp[B(20)+5][22],dis[22][22],len[22];
int n;
 
void Init(){
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            int k;
            dis[i][j]=-1;
            for(k=len[i];k>=1;k--){
                int f=1;
                for(int kk=k,t=1;kk<=len[i]&&t<=len[j];kk++,t++)
                    if(str[i][kk]!=str[j][t]){
                        f=0;
                        break;
                    }
                if(f){
                    if(len[i]-k+1<len[i]&&len[i]-k+1<len[j])
                        dis[i][j]=len[i]-k+1;
                    break;
                }
            }
        }
    }
}
 
int main(){
    char e;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%s",str[i]+1);
            len[i]=strlen(str[i]+1);
        }
        getchar();
        scanf("%c",&e);
        Init();
        memset(dp,-1,sizeof dp);
        int full=B(n)-1;
        for(int i=0;i<n;i++){
            if(str[i][1]==e)
                dp[B(i)][i]=len[i];
        }
        int ans=0;
        for(int s=0;s<=full;s++){
            for(int i=0;i<n;i++){
                if(dp[s][i]==-1)continue;
                if(!(s&B(i)))continue;
                for(int j=0;j<n;j++){
                    if(i==j)continue;
                    if(s&B(j))continue;
                    if(dis[i][j]==-1)continue;
                    cmax(dp[s|B(j)][j],dp[s][i]+len[j]-dis[i][j]);
                }
                cmax(ans,dp[s][i]);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}






D题
这题又是dp。。。
dp[i][j]表示i这个数,分成j份能对应的方案数。
状态转移返程:dp[i][j]=dp[i-j][j]+dp[i-1][j-1];


#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const int MOD=1000000007;


int main(){
    int n,k,dp[220][7];
    while(scanf("%d%d",&n,&k)!=EOF){
        memset(dp,0,sizeof dp);
        dp[0][0]=1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=k;j++){
                if(i-j>=0)
                    dp[i][j]=dp[i-j][j]+dp[i-1][j-1];
            }
        }
        printf("%d\n",dp[n][k]);
    }
}




F题
题意很简单,就是求两个串公约串的个数。
要得到公约串,首先要得到两个串的next数组求出两个串的最小循环节;
接下来要判断四种情况:
1、a==len1&&b==len2
2、a==len1&&b==len1
3、a==len2&&b==len2
4、a==b;
注:a表示1串的最短循环节,b表示2串的最短循环节。
情况1:判断两个串是否相同,相同有1个公约串,不相同则没有;
情况2和3是相同的,那么考虑情况2:既然a==b,肯定要判断1和2串长度为a的前缀是否相同,如果相同公约串肯定是1,否则是0;
情况4:123都不满足,开始没确定是否一定要a==b。假设我们不知道a==b,那么我们要取这两个的公倍数,判断这样长度的前缀是否相同,相同就进入下一步
下一步需要做的就是不断倍增这个公倍数,判断是否能同时被两个串的长度整除。后来发现其实a==b是一定的。


#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define B(x) (1<<(x))
typedef long long ll;
const int oo=0x3f3f3f3f;
const ll OO=1LL<<61;
const ll MOD=10007;
const int maxn=100000+5;
char s1[maxn],s2[maxn];
int Next[maxn];//这里用next会编译错
 
void get_next(char s[],int len){
    int i=0;
    Next[i]=-1;
    int j=-1;
    while(i<len){
        if(j==-1||s[i]==s[j]){
            i++;j++;
            Next[i]=j;
        }
        else j=Next[j];
    }
}
 
int Strcmp(char ss[],char se[],char ts[],char te[]){
    while(ss!=se){
        if(*ss!=*ts)
            return *ss-*ts;
        ss++;
        ts++;
    }
    return 0;
}
 
int gcd(int a,int b){
    return b==0 ? a : gcd(b,a%b);
}
 
int main(){
    int len1,len2,a,b,ans;
    while(scanf("%s%s",s1,s2)!=EOF){
        a=len1=strlen(s1);
        b=len2=strlen(s2);
        get_next(s1,len1);
        if(len1%(len1-Next[len1])==0) a=len1-Next[len1];
        get_next(s2,len2);
        if(len2%(len2-Next[len2])==0) b=len2-Next[len2];
        ans=0;
        if(a==len1&&b==len2){
            if(strcmp(s1,s2)==0)
                ans=1;
            else
                ans=0;
        }
        else if(a==len1){
            ans=0;
            if(b==len1)
            if(Strcmp(s1,s1+a,s2,s2+a)==0)
                ans=1;
        }
        else if(b==len2){
            ans=0;
            if(a==len2)
            if(Strcmp(s1,s1+b,s2,s2+b)==0)
                ans=1;
        }
        else if(a==b){
            int l=a/gcd(max(a,b),min(a,b))*b;
            int t=l;
            ans=0;
            if(l<=len1&&l<=len2&&Strcmp(s1,s1+l,s2,s2+l)==0)
                while(l<=len1&&l<=len2){
                    if(len1%l==0&&len2%l==0)
                        ans++;
                    l+=t;
                }
        }
        printf("%d\n",ans);
    }
    return 0;
}


其他的未能ac,呵呵,写的不好之处请多见谅。


E题标程:

#include <iostream>
using namespace std;

const int MAX = 1000;
const int INF = 100000000;

int edgeCost[MAX];
int nedges;

class Edge
{
public:
    int w;
    int icost;
    Edge *next;

    Edge(int ww, int cc, Edge* n) : w(ww), icost(cc), next(n)
    {}

    int cost() {
        return edgeCost[icost];
    }
};

class Vertex
{
public:
    Edge *adj;
    int prev, cost;
    int numEdges;
    bool visited;

    Vertex() : adj(0), prev(-1), cost(INF) {}

    void init()
    {
        prev = -1;
        cost = INF;
        numEdges = 0;
        visited = false;
    }

    void addEdge(int w, int cost)
    {
        if (adj == 0 || w < adj->w) {
            adj = new Edge(w, cost, adj);
            return;
        }
        Edge *p = adj;
        while (p->next != 0 && w > p->w)
            p = p->next;
        p->next = new Edge(w, cost, p->next);
    }
} cities[MAX+1];

int bestCost;
int bestPath[MAX+1];
int bestPathLength;


int nextMinVertex(int n)
{
    int ans = -1;
    int cost = INF;
    for(int i=1; i<n; i++) {
        if (!cities[i].visited && cities[i].cost < cost) {
            cost = cities[i].cost;
            ans = i;
        }
    }
    return ans;
}

bool betterPath(int e)
{
    if (cities[e].numEdges < bestPathLength)
        return true;
    else if (cities[e].numEdges > bestPathLength)
        return false;
    else {
        int path[MAX];
        int v=e;
        for(int i=cities[e].numEdges; i>=0; i--) {
            path[i] = v;
            v = cities[v].prev;
        }
        for(int i=0; i<cities[e].numEdges; i++)
            if (path[i] < bestPath[i])
                return true;
            else if (path[i] > bestPath[i])
                return false;
        return false;
    }
}

void dijkstra(int s, int e, int n)
{
    for(int i=0; i<n; i++)
        cities[i].init();
    cities[0].cost = 0;
    int v=0;
    while (true) {
cout << "visiting vertex " << v << endl;
        cities[v].visited = true;
        if (v == -1) {
            cout << "ERROR: can't reach 1" << endl;
            exit(-1);
        }
        if (v == e)
            break;
        for(Edge *e = cities[v].adj; e!=0; e=e->next) {
            int w = e->w;
            if (cities[v].cost + e->cost() < cities[w].cost) {
//cout << "  updating vertex " << w << " with new cost " << cities[v].cost +e->cost() << endl;;
                cities[w].cost = cities[v].cost + e->cost();
                cities[w].prev = v;
                cities[w].numEdges = cities[v].numEdges+1;
            }
        }
        v = nextMinVertex(n);
    }
    if (cities[e].cost == 0)
        return;
    if (cities[e].cost < bestCost || (cities[e].cost == bestCost && betterPath(e))) {
        bestCost = cities[e].cost;
        v = e;
        for(int i=cities[e].numEdges; i>=0; i--) {
            bestPath[i] = v;
            v = cities[v].prev;
        }
        bestPathLength = cities[e].numEdges;
    }
}

int main()
{
    int n;
    cin >> n;
    while (n > 0) {
        for(int i=0; i<=n; i++) {
            cities[i].adj = 0;
        }
        nedges=0;
        int ncities = 0;
        for(int i=0; i<n; i++) {
            int s, e, cost;
            cin >> s >> e >> cost;
            edgeCost[nedges] = cost;
            cities[s].addEdge(e, nedges);
            cities[e].addEdge(s, nedges);
            nedges++;
            if (s > ncities)
                ncities = s;
            if (e > ncities)
                ncities = e;
        }
        ncities++;

        bestCost = INF;
        dijkstra(0, 1, ncities);
        for(int i=0; i<nedges; i++) {
            int icost = edgeCost[i];
            edgeCost[i]= 0;
            dijkstra(0, 1, ncities);
            for(int j=i+1; j<nedges; j++) {
                int jcost = edgeCost[j];
                edgeCost[j]= 0;
                dijkstra(0, 1, ncities);
                edgeCost[j]= jcost;
            }
            edgeCost[i]= icost;
        }
        for(int i=0; i<=bestPathLength; i++)
            cout << bestPath[i] << ' ';
        cout << bestCost << endl;
                    
        cin >> n;
    }
}



G题标程:

#include <iostream>
using namespace std;


const int MAXEDGES = 200;
const int MAXBORDERS = 20;


long perims[MAXBORDERS+1];
long areas[MAXBORDERS+1];
class Edge
{
public:
int x1, y1, x2, y2;
int dx1, dx2, dy1, dy2;
bool isHoriz;
bool clipped;


Edge()
{}


Edge(int nx1, int nx2, int ny1, int ny2, int d)
{
set(nx1, nx2, ny1, ny2, d);
}


Edge(int nx1, int nx2, int ny1, int ny2, int ndx1, int ndx2, int ndy1, int ndy2)
{
x1 = nx1;
x2 = nx2;
y1 = ny1;
y2 = ny2;
dx1 = ndx1;
dx2 = ndx2;
dy1 = ndy1;
dy2 = ndy2;
isHoriz = (dy1==dy2);
clipped = false;
}


Edge nextEdge()
{
return *(new Edge(x1+dx1, x2+dx2, y1+dy1, y2+dy2, dx1, dx2, dy1, dy2));
}


void set(int nx1, int nx2, int ny1, int ny2, int d)
{
x1 = nx1;
x2 = nx2;
y1 = ny1;
y2 = ny2;
if (y1 == y2) {
if (x1 < x2) {
dx1 = -d;
dx2 = dy1 = dy2 = d;
}
else {
dx1 = d;
dx2 = dy1 = dy2 = -d;
}
}
else if (y1 < y2) {
dy2 = d;
dy1 = dx1 = dx2 = -d;
}
else {
dy2 = -d;
dy1 = dx1 = dx2 = d;
}
isHoriz = (dy1==dy2);
clipped = false;
}
};


class BPiece
{
public:
Edge e[MAXEDGES];
int numE;
};


class Border
{
public:
BPiece piece[MAXEDGES/4];
int nPieces;
int perim;


Border()
{
nPieces = perim = 0;
for(int i=0; i<MAXEDGES/4; i++)
piece[i].numE = 0;
}
};


bool between(int a, int b, int c)
{
if (a>=b && a <=c)
return true;
else
return (a<=b && a>=c);
}


long calcPerim(Border *border)
{
long perim=0;
for(int i=0; i<border->nPieces; i++) {
BPiece *bpiece = border->piece+i;
for(int j=0; j<bpiece->numE; j++) {
Edge *e = bpiece->e+j;
perim += abs(e->x1-e->x2) + abs(e->y1-e->y2);
}
}
return perim;
}


long calcArea(Border *border)
{
long area=0;
for(int i=0; i<border->nPieces; i++) {
BPiece *bpiece = border->piece+i;
for(int j=0; j<bpiece->numE; j++) {
Edge *e = bpiece->e+j;
area += (e->x2-e->x1)*(e->y1);
}
}
return area;
}


bool clipHoriz(Edge& e, BPiece& elist, int d, int cx1, int cy1, int cx2, int cy2)
{
int x1in = (e.x1 < cx1 ? -1 : e.x1 <= cx2 ? 0 : 1);
int x2in = (e.x2 < cx1 ? -1 : e.x2 <= cx2 ? 0 : 1);
bool y1in = (e.y1 > cy1 && e.y1 < cy2);
bool y2in = (e.y2 > cy1 && e.y2 < cy2);
if (x1in==0 && x2in==0 && y1in && y2in) {// inside prev border
e.clipped = true;
return true;
}
else if (!y1in || !y2in) {// no need to clip
return false;
}
else if (x1in*x2in < 0) {// break into two pieces
if (e.x1 < e.x2) {
elist.e[elist.numE++].set(cx2, e.x2, e.y1, e.y2, d);
e.x2 = cx1;
}
else {
elist.e[elist.numE++].set(cx1, e.x2, e.y1, e.y2, d);
e.x2 = cx2;
}
return false;
}
else if (x1in == 0) {
if (e.x1 < e.x2)
e.x1 = cx2;
else
e.x1 = cx1;
}
else if (x2in == 0) {
if (e.x2 < e.x1)
e.x2 = cx2;
else
e.x2 = cx1;
}
return false;
}


bool clipVert(Edge& e, BPiece& elist, int d, int cx1, int cy1, int cx2, int cy2)
{
bool x1in = (e.x1 > cx1 && e.x1 < cx2);
bool x2in = (e.x2 > cx1 && e.x2 < cx2);
int y1in = (e.y1 < cy1 ? -1 : e.y1 <= cy2 ? 0 : 1);
int y2in = (e.y2 < cy1 ? -1 : e.y2 <= cy2 ? 0 : 1);
if (x1in && x2in && y1in==0 && y2in==0) {// inside prev border
e.clipped = true;
return true;
}
else if (!x1in || !x2in) {// no need to clip
return false;
}
else if (y1in*y2in<0) {// break into two pieces
if (e.y1 < e.y2) {
elist.e[elist.numE++].set(e.x1, e.x2, cy2, e.y2, d);
e.y2 = cy1;
}
else {
elist.e[elist.numE++].set(e.x1, e.x2, cy1, e.y2, d);
e.y2 = cy2;
}
return false;
}
else if (y1in==0) {
if (e.y1 < e.y2)
e.y1 = cy2;
else
e.y1 = cy1;
}
else if (y2in==0) {
if (e.y2 < e.y1)
e.y2 = cy2;
else
e.y2 = cy1;
}
return false;
}


BPiece clip(Edge e, int genPiece, int genEdge, Border* bdr, int d)
{
BPiece ans;
bool clipped = false;
ans.e[0] = e;
ans.numE = 1;
for(int i=0; i<ans.numE; i++) {
bool exit = false;
for(int j=0; j<bdr->nPieces; j++) {
for(int k=0; k<bdr->piece[j].numE; k++) {
if (j == genPiece && k == genEdge)
continue;
Edge* bdre = bdr->piece[j].e+k;
if (e.isHoriz) {// horizontal edge
if (bdre->isHoriz) {
clipped = clipHoriz(ans.e[i], ans, d, min(bdre->x1, bdre->x2)-d, bdre->y1-d, max(bdre->x1, bdre->x2)+d, bdre->y1+d);
}
else {
clipped = clipHoriz(ans.e[i], ans, d, bdre->x1-d, min(bdre->y1, bdre->y2)-d, bdre->x1+d, max(bdre->y1, bdre->y2)+d);
}
}
else {
if (bdre->isHoriz) {
clipped = clipVert(ans.e[i], ans, d, min(bdre->x1, bdre->x2)-d, bdre->y1-d, max(bdre->x1, bdre->x2)+d, bdre->y1+d);
}
else {
clipped = clipVert(ans.e[i], ans, d, bdre->x1-d, min(bdre->y1, bdre->y2)-d, bdre->x1+d, max(bdre->y1, bdre->y2)+d);
}
}
if (clipped) {
for(int ii=i+1; ii<ans.numE; ii++) {
ans.e[ii-1] = ans.e[ii];
}
ans.numE--;
i--;
exit = true;
break;
}
}
if (exit)
break;
}
}
return ans;
}


bool add(Edge e, BPiece &piece)
{
int i = piece.numE;
if (i == 0) {
piece.e[0] = e;
piece.numE++;
return true;
}
i--;
if (e.isHoriz != piece.e[i].isHoriz) {
if (e.x1 == piece.e[i].x2 && e.y1 == piece.e[i].y2) {
piece.e[i+1] = e;
piece.numE++;
return true;
}
}
else if (e.isHoriz && e.y1 == piece.e[i].y1) {
if (between(e.x1, piece.e[i].x1, piece.e[i].x2)) {
piece.e[i].x2 = e.x2;
return true;
}
}
else if (!e.isHoriz && e.x1 == piece.e[i].x1) {
if (between(e.y1, piece.e[i].y1, piece.e[i].y2)) {
piece.e[i].y2 = e.y2;
return true;
}
}
return false;
}


int main()
{
int ncase, n, m, d;
cin >> ncase;
for(int icase=1; icase<=ncase; icase++) {
cout << "Case " << icase << ":" << endl;
cin >> n >> m >> d;
Border* prevB = new Border;
prevB->nPieces = 1;
prevB->piece[0].numE = n;
int x1, x2, y1, y2, sx1, sy1;
cin >> x1 >> y1;
sx1=x1;
sy1=y1;
for(int i=0; i<n-1; i++) {
cin >> x2 >> y2;
prevB->piece[0].e[i].set(x1, x2, y1, y2, d);
x1 = x2;
y1 = y2;
}
prevB->piece[0].e[n-1].set(x1, sx1, y1, sy1, d);


areas[0] = calcArea(prevB);
cout << "  Perimeters:";
for(int iB = 1; iB<=m; iB++) {
Border* currB = new Border;
for(int i=0; i<prevB->nPieces; i++) {
for(int j=0; j<prevB->piece[i].numE; j++) {
BPiece elist = clip(prevB->piece[i].e[j].nextEdge(), i, j, prevB, d);
for(int k=0; k<elist.numE; k++) {
int l=0;
while (l < currB->nPieces) {
if (add(elist.e[k], currB->piece[l]))
break;
l++;
}
if (l == currB->nPieces) {
add(elist.e[k], currB->piece[l]);
currB->nPieces++;
}
}
}
}
cout << " " << calcPerim(currB);
areas[iB] = calcArea(currB);

prevB = currB;
}
cout << "\n  Areas:";
for(int iB = 1; iB<=m; iB++) {
cout << " " << areas[iB]-areas[iB-1];
}
cout << endl;
if (icase < ncase)
cout << endl;


}
return 0;
}







































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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值