H - Sorting Slides
应该是个二分匹配的模板题的,但我还不会写 = =
好在数据规模小,就用贪心的方法水过了(没加vis判冲突wa了几发,从此开始艰难的没有1A 的生活)
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
typedef long long ll;
struct slide{
int x1,x2,y1,y2;
}rec[50];
int g[100][100],d[100],ans[50],vis[100];
int main(){
//freopen("r.in","r",stdin);freopen("r.out","w",stdout);
int n,cs=1;
while(scanf("%d",&n) && n){
for(int i=0;i<n;i++)scanf("%d%d%d%d",&rec[i].x1,&rec[i].x2,&rec[i].y1,&rec[i].y2);
int x,y;
memset(d,0,sizeof d);
memset(g,0,sizeof g);
memset(vis,0,sizeof vis);
memset(ans,-1,sizeof ans);
for(int i=0;i<n;i++){
scanf("%d%d",&x,&y);
for(int j=0;j<n;j++)if(x<rec[j].x2&&x>rec[j].x1&&y<rec[j].y2&&y>rec[j].y1){
g[i][j+n]=1;d[i]++;
d[j+n]++;
}
}
int flag=1;
while(flag){
int i,j,i0,j0;
flag=0;
for(i=0;i<n;i++)if(!vis[i]&&d[i]==1)
{flag=1;break;}
if(flag){
for(j=n;j<2*n;j++)if(!vis[j]&&g[i][j])break;
i0=i,j0=j;
ans[j0-n]=i0;
vis[i0]=vis[j0]=1;
g[i0][j0]=0;d[i0]--;d[j0]--;
for(i=0;i<n;i++)if(g[i][j0])d[i]--,g[i][j0]=0;
continue;
}
for(j=n;j<2*n;j++)if(!vis[j]&&d[j]==1)
{flag=1;break;}
if(flag){
for(i=0;i<n;i++)if(!vis[i]&&g[i][j])break;
i0=i;j0=j;
ans[j0-n]=i0;
vis[i0]=vis[j0]=1;
g[i0][j0]=0;d[i0]--;d[j0]--;
for(j=n;j<2*n;j++)if(g[i0][j])d[j]--,g[i0][j]=0;
continue;
}
}
int cnt=0;
printf("Heap %d\n",cs++);
for(int i=0;i<n;i++)if(ans[i]>=0)
{if(cnt)printf(" ");printf("(%c,%d)",'A'+i,ans[i]+1);cnt++;}
if(!cnt)printf("none");
printf("\n\n");
}
return 0;
}
A - Triangle Encapsulation
不能更水。
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
typedef long long ll;
struct point {
int x,y;
struct point operator -(const struct point b){
struct point c;
c.x=x-b.x;c.y=y-b.y;
return c;
}
}p[5];
int cmp(struct point a,struct point b){
if(a.y-b.y)return a.y>b.y;
return a.x<b.x;
}
int g[20][20];
int cross(struct point a,struct point b){
return a.x*b.y-a.y*b.x;
}
int main(){
//freopen("r.in","r",stdin);freopen("r.out","w",stdout);
printf("Program 4 by team X\n");
while(scanf("%d%d",&p[0].x,&p[0].y)!=EOF){
for(int i=1;i<3;i++)scanf("%d%d",&p[i].x,&p[i].y);
struct point pi;
memset(g,0,sizeof g);
int xmin=18,ymin=18,ymax=0,xx[20]={0};
for(pi.x=-9;pi.x<=9;pi.x++)
for(pi.y=-9;pi.y<=9;pi.y++){
int c1=0,c2=0;
for(int i=0;i<3;i++){
if(cross(pi-p[i],pi-p[(i+1)%3])<0)c1++;
if(cross(pi-p[i],pi-p[(i+1)%3])>0)c2++;
}
if(c1==3||c2==3){
g[pi.x+9][pi.y+9]=1;
xmin=min(xmin,pi.x+9);
xx[pi.y+9]=max(xx[pi.y+9],pi.x+9);
ymin=min(ymin,pi.y+9);
ymax=max(ymax,pi.y+9);
}
}
int x,y;
for(y=ymax;y>=ymin;y--){
for(x=xmin;x<=xx[y];x++){
if(x>xmin)printf(" ");
if(g[x][y])printf("(%2d,%3d)",x-9,y-9);
else printf(" ");
}
printf("\n");
}
printf("\n");
}
printf("End of program 4 by team X\n");
return 0;
}
G - Reflections
几何题。解析算错很多次,其实就是算交点和关于直线对称。用向量不容易错。
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <utility>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
#define eps 1e-6
typedef long long ll;
int n,ans[30],cur;
struct point{
double x,y;
};
struct circle{
double x,y,r;
}cir[30];
struct line{
double x0,y0,dx,dy;
}ori;
int sgn(double x){
if(x>eps)return 1;
if(x<-eps)return -1;
return 0;
}
pair <double,int> inter(struct line now){
double a,b,c,del,t1,t2,t=-1;
int use=-1;
for(int i=1;i<=n;i++){
a=now.dx*now.dx+now.dy*now.dy;
b=now.dx*(now.x0-cir[i].x)+now.dy*(now.y0-cir[i].y);
c=(now.x0-cir[i].x)*(now.x0-cir[i].x)+(now.y0-cir[i].y)*(now.y0-cir[i].y)-cir[i].r*cir[i].r;
del=b*b-a*c;
if(sgn(del)<=0)continue;
t1=(-b-sqrt(del))/a;
t2=(-b+sqrt(del))/a;
if(sgn(t1)>0){
if(t==-1||t>t1)t=t1,use=i;
}
else if(sgn(t2)>0){
if(t==-1||t>t2)t=t2,use=i;
}
}
return make_pair(t,use);
}
void work(struct line now){
if(cur>10)return;
double t=inter(now).first;
if(t<=0)return;
int i0=ans[cur++]=inter(now).second;
/* 求对称射线 */
double x,y,xx,yy;
x=now.x0+t*now.dx;
y=now.y0+t*now.dy;
if(sgn(now.dy*(x-cir[i0].x)-now.dx*(y-cir[i0].y))==0){
now.x0=x;now.y0=y;
now.dx=-now.dx;now.dy=-now.dy;
work(now);
return;
}
xx=-((x-cir[i0].x)*now.dx+(y-cir[i0].y)*now.dy)/cir[i0].r;
yy=((x-cir[i0].x)*now.dy-(y-cir[i0].y)*now.dx)/cir[i0].r;
now.x0=x;now.y0=y;
now.dx=(xx*(x-cir[i0].x)-yy*(y-cir[i0].y))/cir[i0].r;
now.dy=(xx*(y-cir[i0].y)+yy*(x-cir[i0].x))/cir[i0].r;
work(now);
}
int main(){
//freopen("r.in","r",stdin);freopen("r.out","w",stdout);
int cs=1;
while(scanf("%d",&n) && n){
int i;
for(i=1;i<=n;i++)scanf("%lf%lf%lf",&cir[i].x,&cir[i].y,&cir[i].r);
scanf("%lf%lf%lf%lf",&ori.x0,&ori.y0,&ori.dx,&ori.dy);
cur=0;
work(ori);
printf("Scene %d\n",cs++);
for(i=0;i<cur&&i<10;i++)printf("%d ",ans[i]);
if(cur>10)printf("...\n\n");
else printf("inf\n\n");
}
return 0;
}
C - Robbery
一开始有点不敢写,想了一下其实每个时间点只和前后两个点有关,所以正着跑一次再倒着check一遍就确定了。
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
typedef long long ll;
int w,h,T,n;
int g[105][105][105];
struct message{
int t,l,u,r,d;
}mes[105];
struct answer{
int t,x,y;
}ans[105];
int cmp(struct message a,struct message b){
return a.t<b.t;
}
void direct(){
int k=0;
memset(g,-1,sizeof g);
memset(g[1],0,sizeof g[1]);
for(int t=1;t<=T;t++){
//to expand reachable area.
if(t>1)
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)if(!g[t-1][i][j]){
g[t][i][j]=0;
if(i>1)g[t][i-1][j]=0;
if(j>1)g[t][i][j-1]=0;
if(i<h)g[t][i+1][j]=0;
if(j<w)g[t][i][j+1]=0;
}
//to receive the messge.
for(;k<n&&mes[k].t==t;k++){
for(int i=mes[k].u;i<=mes[k].d;i++)
for(int j=mes[k].l;j<=mes[k].r;j++)
g[t][i][j]=-1;
}
}
}
void inverse(){
int k=n-1;
for(int t=T-1;t>0;t--){
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)if(!g[t][i][j]){
if(!g[t+1][i][j])continue;
if(i>1&&!g[t+1][i-1][j])continue;
if(j>1&&!g[t+1][i][j-1])continue;
if(i<h&&!g[t+1][i+1][j])continue;
if(j<w&&!g[t+1][i][j+1])continue;
g[t][i][j]=-1;
}
}
}
int main(){
//freopen("r.in","r",stdin);freopen("r.out","w",stdout);
int cs=1;
while(scanf("%d%d%d",&w,&h,&T) && w){
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d%d%d%d",&mes[i].t,&mes[i].l,&mes[i].u,&mes[i].r,&mes[i].d);
sort(mes,mes+n,cmp);
direct();
inverse();
printf("Robbery #%d:\n",cs++);
int res=0,flag=1;
for(int t=1;t<=T;t++){
int cn=0,x,y;
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)if(!g[t][i][j])x=i,y=j,cn++;
if(!cn){flag=0;break;}
if(cn==1)ans[res].t=t,ans[res].x=x,ans[res++].y=y;
}
if(!flag)printf("The robber has escaped.\n\n");
else{
if(!res)printf("Nothing known.\n\n");
else{
for(int i=0;i<res;i++)printf("Time step %d: The robber has been at %d,%d.\n",ans[i].t,ans[i].y,ans[i].x);
printf("\n");
}
}
}
return 0;
}
E - Triangle War
状压dp,极大极小算法。
另外有个坑点是每次不一定要把能取的三角形位置都取完。。
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
typedef long long ll;
int edge[15][15],tri[10]={7,152,52,352,34304,3200,71680,12544,155648};
int dp[1<<18];
int check(int sta){
int ans=0;
for(int i=0;i<9;i++)if((sta&tri[i])==tri[i])ans++;
return ans;
}
void dfs(){
int s=(1<<18)-1;
dp[s]=0;
for(s=s-1;s>=0;s--){
int ori=check(s),cn,maxdp=-10;
for(int i=0;i<18;i++)if(!((1<<i)&s)){
int to=(1<<i)|s;
int temp=check(to)-ori;
if(temp)temp+=dp[to];
else temp-=dp[to];
maxdp=max(maxdp,temp);
}
dp[s]=maxdp;
}
}
int main(){
//freopen("r.in","r",stdin);freopen("r.out","w",stdout);
int t,gm,G;
edge[1][2]=1;edge[1][3]=1<<1;
edge[2][3]=1<<2;edge[2][4]=1<<3;edge[2][5]=1<<4;
edge[3][5]=1<<5;edge[3][6]=1<<6;
edge[4][5]=1<<7;edge[4][7]=1<<9;edge[4][8]=1<<10;
edge[5][6]=1<<8;edge[5][8]=1<<11;edge[5][9]=1<<12;
edge[6][9]=1<<13;edge[6][10]=1<<14;
edge[7][8]=1<<15;edge[8][9]=1<<16;edge[9][10]=1<<17;
dfs();
scanf("%d",&t);
while(t--){
scanf("%d",&G);
for(gm=1;gm<=G;gm++){
int m,sta=0,u,v,turn=0;
int a[2]={0};
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
int ori=check(sta);
sta+=edge[u][v];
ori=check(sta)-ori;
a[turn]+=ori;
if(!ori)turn=!turn;
}
printf("Game %d: ",gm);
a[turn]+=dp[sta];
if(a[0]>a[1])printf("A wins.\n");
else printf("B wins.\n");
}
if(t)printf("\n");
}
return 0;
}
D - Dreisam Equations
就是暴力加表达式计算。一直SegmentationFault不明所以,发现是代表符号的值取的不好会和数值冲突=_=
#include <stdio.h>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <stack>
using namespace std;
#define lson o<<1
#define rson o<<1|1
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define INF 200000000
#define zuokuo 200000000
#define youkuo 200000001
#define kong 200000009
#define jia -200000000
#define jian -200000001
#define cheng -200000002
typedef long long ll;
char eq[1000];
int q[1000],res;
int lf;
stack <int> a;
stack <int> s;
int solve(int cur){
if(cur==res){
while(!a.empty())a.pop();
while(!s.empty())s.pop();
for(int i=0;i<res;i++){
if(q[i]>-200000000&&q[i]<200000000){
if(s.empty()||s.top()==zuokuo)a.push(q[i]);
else{
int u=a.top();a.pop();
if(s.top()==jia)a.push(u+q[i]);
if(s.top()==jian)a.push(u-q[i]);
if(s.top()==cheng)a.push(u*q[i]);
s.pop();
}
}
else if(q[i]==youkuo){
if(s.empty()||s.top()!=zuokuo)return 0;
s.pop();
if(s.empty()||s.top()==zuokuo)continue;
int u=a.top();a.pop();
int v=a.top();a.pop();
if(s.top()==jia)a.push(v+u);
if(s.top()==jian)a.push(v-u);
if(s.top()==cheng)a.push(v*u);
s.pop();
}
else s.push(q[i]);
}
if(a.top()==lf)return 1;
else return 0;
}
if(q[cur]!=kong)return solve(cur+1);
for(int i=cheng;i<=jia;i++){
q[cur]=i;
if(solve(cur+1))return 1;
q[cur]=kong;
}
return 0;
}
int main(){
int cs=1;
while(gets(eq) && eq[0]!='0'){
sscanf(eq,"%d",&lf);
res=0;
int i;
for(i=0;eq[i]!='=';i++);
for(i++;eq[i]!='\0';i++){
for(;eq[i]==' ';i++);
if(eq[i]=='('){q[res++]=zuokuo;continue;}
if(eq[i]==')'){q[res-1]=youkuo;q[res++]=kong;continue;}
int num=0;
while(eq[i]>='0'&&eq[i]<='9'){
num=num*10+eq[i]-'0';
i++;
}
q[res++]=num;
q[res++]=kong;
i=i-1;
}
res=res-1;
printf("Equation #%d:\n",cs++);
if(solve(0)==0)printf("Impossible\n\n");
else{
printf("%d=",lf);
for(int i=0;i<res;i++){
if(q[i]==zuokuo)printf("(");
else if(q[i]==youkuo)printf(")");
else if(q[i]==jia)printf("+");
else if(q[i]==jian)printf("-");
else if(q[i]==cheng)printf("*");
else printf("%d",q[i]);
}
printf("\n\n");
}
}
return 0;
}