下午的群赛题解由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;
}