2015多校联合训练总结(2)
2015-07-27 19:46
323 查看
相比较第一场,少了些许紧张,但是同样暴露了我们三人配合上的问题,开始被大神一句:第七道是一道水线段树,于是便直奔去搞线段树,结果这个题是过的人数最少的题之一~然后我们三人一人读一道题,甚至开始自己鼓捣怎么写,于是很长时间大家都在安静的搞自己觉得可能会搞出来的题,于是乎很长时间,都没有结果,然后大家慢慢弃疗,开始专注的考虑一道题,最终ac了一道。所以在慢慢的训练中我们才会共同成长吧~~
下面是其中某些题的题解
A:http://acm.hdu.edu.cn/showproblem.php?pid=5300
题很长,过的人很少很少,放弃
B:http://acm.hdu.edu.cn/showproblem.php?pid=5301
题意:n*m的矩阵里面有一个1*1的小黑块,用大小不同的小矩形铺满n*m的矩形,不能覆盖小黑块,只能相接,同时这些小矩形必须满足至少有一边在大矩形的边框上,使得这些小矩形都尽量小,使得面积最大的小矩形面积最小,这个小矩形面积多大
思路:读题费了很长时间,“minimize the maximum areas of all apartments”,在图文并茂下终于读懂了,第一感觉就是一个机智题,大致找了一规律。就是最短边加1的一半,如果在黑块正好在正方形的正中间,那么就减一,预料中的wa了、、然后就开始考虑特殊情况,那就是类似于这种的
按照最初的思路,结果应该是2,但是明显的,不符合条件,所以我又用了另一种方法,求小黑块四个方向距离四边的最小值,并取四个最小值中的最大值,然后用这两种结果取最大值,就是结果,最终ac了
过程中还卡了很久,原因竟然是n和m弄反了。。。。TnT
代码:
C:http://acm.hdu.edu.cn/showproblem.php?pid=5302
题意:给你六个点,分别是白点度为0的有a1个,白点度为1的有a2个,白点度为2的点有a3个,黑色的度为0的点b1个,黑点度为1的点有b2个,黑色度为2的点有b3个,同时要求白点个数等于黑点个数,要求构造一个图满足这个条件
思路:若a2&1 或b2&1 则无解。度为1的点必须成对存在,在这只有0 1 2度数的图中。白色边和黑色边不相互影响,他们是独立的。总的边数为总度数/2 。即:(a2+a3*2)/2.
先构造白边度数为2的点,必然是(1,2)(2,3)(3,4)....(a3+1,a3+2)..如此下去,直到完成度数2的节点的构造。
再够着白边度数为1的点,(a3+3,a3+4) (a3+5,a3+6).......
最后白色边度数为0的点,(,)(,)...(a1+a2+a3,a1+a2+a3)
代码:
D:http://acm.hdu.edu.cn/showproblem.php?pid=5303
题意:一个圆形环道上有n棵苹果树,从顺时针方向看,每个苹果树分别上距离原点分别有di米的位置,有ai个苹果,每次最多能拿k个苹果,若要把所有苹果都摘到原点,问最少需要走多少米
思路:如果道路不是环形的,那么就把道路平均截成两段贪心即可,但是这样有一个问题,就是有时候可能需要走整个环,但是可能想到的是这个环最多只会走1次,因为如果走两次的话,可以分别走两个半环, 接下来的处理两种思路,一种是左右两侧分别以每k个一组,剩下的分别采取1.走一圈,左边剩余的单独一回,2.走一圈,右边剩余的单独一回,3.左侧的单独走,右侧的单独走,三种方式找最小的。第二种是记录摘取每个苹果所需要的累计的路程,然后把最后一个作为所用路程的一半,暴力从左侧都包含,逐渐右移,再到全右侧,找了最小的。
代码:(第二种方法)
E:状压dp
F:http://acm.hdu.edu.cn/showproblem.php?pid=5305
题意:给你n个人,这n个人构成m对朋友,现在想要这n个人每个人都拥有相等的线上朋友和线下朋友,问能不能实现,如果不能输出0,否则输出有几种方式
思路:dfs搜索,分别假设第i对朋友是线上朋友,要努力保证线上朋友和线下朋友相等,以此类推,直到最后一个,如果这m对都满足,那么sum++,最后的sum就是所要求的结果
代码:
G:暴力线段树,开头听了大神言,小伙伴写了半个多小时,无结果,弃疗、、
H:FFT快速傅氏变换,复变中的傅氏变换都没学明白,对于FFT代码、、
I:http://acm.hdu.edu.cn/showproblem.php?pid=5308
题意:用n个n用+、-、*、/、()这几个符号得到24点
思路:暴力找规律,直接输出
代码:
J:DP弃疗~
下面是其中某些题的题解
A:http://acm.hdu.edu.cn/showproblem.php?pid=5300
题很长,过的人很少很少,放弃
B:http://acm.hdu.edu.cn/showproblem.php?pid=5301
题意:n*m的矩阵里面有一个1*1的小黑块,用大小不同的小矩形铺满n*m的矩形,不能覆盖小黑块,只能相接,同时这些小矩形必须满足至少有一边在大矩形的边框上,使得这些小矩形都尽量小,使得面积最大的小矩形面积最小,这个小矩形面积多大
思路:读题费了很长时间,“minimize the maximum areas of all apartments”,在图文并茂下终于读懂了,第一感觉就是一个机智题,大致找了一规律。就是最短边加1的一半,如果在黑块正好在正方形的正中间,那么就减一,预料中的wa了、、然后就开始考虑特殊情况,那就是类似于这种的
按照最初的思路,结果应该是2,但是明显的,不符合条件,所以我又用了另一种方法,求小黑块四个方向距离四边的最小值,并取四个最小值中的最大值,然后用这两种结果取最大值,就是结果,最终ac了
过程中还卡了很久,原因竟然是n和m弄反了。。。。TnT
代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <iostream> #include <algorithm> #include <string> #include <vector> #include <deque> #include <list> #include <set> #include <map> #include <stack> #include <queue> #include <cctype> #include <numeric> #include <iomanip> #include <bitset> #include <sstream> #include <fstream> #define debug "output for debug\n" #define pi (acos(-1.0)) #define eps (1e-8) #define inf 0x3f3f3f3f #define ll long long using namespace std; const int maxn = 1000005; int main() { ll n,m,x,y; ll a[10]; while(scanf("%lld %lld %lld %lld",&n,&m,&x,&y)!=EOF) { if(n==1&&m==1) { printf("0\n"); continue; } if(n==1||m==1||n==2||m==2) { printf("1\n"); continue; } a[0]=min(y-1,x); a[0]=min(a[0],n-x+1); //cout<<a[0]<<endl; a[1]=min(x-1,y); a[1]=min(m-y+1,a[1]); //cout<<a[1]<<endl; a[2]=min(x,m-y); a[2]=min(a[2],n-x+1); //cout<<a[2]<<endl; a[3]=min(y,n-x); a[3]=min(a[3],m-y+1); //cout<<a[3]<<endl; ll maxn=max(max(max(a[0],a[1]),a[2]),a[3]); ll sum=(min(n,m)+1)/2; if(n==m&&n%2&&x==(n+1)/2&&y==(n+1)/2)sum--; printf("%lld\n",max(sum,maxn)); } return 0; }
C:http://acm.hdu.edu.cn/showproblem.php?pid=5302
题意:给你六个点,分别是白点度为0的有a1个,白点度为1的有a2个,白点度为2的点有a3个,黑色的度为0的点b1个,黑点度为1的点有b2个,黑色度为2的点有b3个,同时要求白点个数等于黑点个数,要求构造一个图满足这个条件
思路:若a2&1 或b2&1 则无解。度为1的点必须成对存在,在这只有0 1 2度数的图中。白色边和黑色边不相互影响,他们是独立的。总的边数为总度数/2 。即:(a2+a3*2)/2.
先构造白边度数为2的点,必然是(1,2)(2,3)(3,4)....(a3+1,a3+2)..如此下去,直到完成度数2的节点的构造。
再够着白边度数为1的点,(a3+3,a3+4) (a3+5,a3+6).......
最后白色边度数为0的点,(,)(,)...(a1+a2+a3,a1+a2+a3)
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; int T; int a[5],b[5]; int d[1000005]; int main() { scanf("%d",&T); while(T--) { for(int i = 0; i<3; i++) scanf("%d",&a[i]); for(int i = 0; i<3; i++) scanf("%d",&b[i]); int sum = 0; for(int i = 0; i<3; i++) sum+=a[i]; if( (a[1]&1) || (b[1]&1) ) { puts("-1"); continue; } if(sum==4) { puts("4\n1 2 0\n1 3 0\n2 3 1\n3 4 1"); continue; } printf("%d\n",a[1]/2+a[2]+b[1]/2+b[2]); int t = 1; while(a[2]!=-1) { printf("%d %d 0\n",t,t+1); t++; a[2]--; } t++; while(a[1]!=2) { printf("%d %d 0\n",t,t+1); t+=2; a[1]-=2; } int tt = 0; for(int i = 1; i<=sum; i+=2) d[tt++] = i; for(int i = 2; i<=sum; i+=2) d[tt++] = i; t = 0; while(b[2]!=-1) { printf("%d %d 1\n",min(d[t],d[t+1]),max(d[t],d[t+1])); t++; b[2]--; } t++; while(b[1]!=2) { printf("%d %d 1\n",min(d[t],d[t+1]),max(d[t],d[t+1])); t+=2; b[1]-=2; } } }
D:http://acm.hdu.edu.cn/showproblem.php?pid=5303
题意:一个圆形环道上有n棵苹果树,从顺时针方向看,每个苹果树分别上距离原点分别有di米的位置,有ai个苹果,每次最多能拿k个苹果,若要把所有苹果都摘到原点,问最少需要走多少米
思路:如果道路不是环形的,那么就把道路平均截成两段贪心即可,但是这样有一个问题,就是有时候可能需要走整个环,但是可能想到的是这个环最多只会走1次,因为如果走两次的话,可以分别走两个半环, 接下来的处理两种思路,一种是左右两侧分别以每k个一组,剩下的分别采取1.走一圈,左边剩余的单独一回,2.走一圈,右边剩余的单独一回,3.左侧的单独走,右侧的单独走,三种方式找最小的。第二种是记录摘取每个苹果所需要的累计的路程,然后把最后一个作为所用路程的一半,暴力从左侧都包含,逐渐右移,再到全右侧,找了最小的。
代码:(第二种方法)
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cstdlib> using namespace std; typedef long long ll; int x[2111111];int n; int l,k; int a1[2111111],n1,a2[2111111],n2; ll ans=0; ll su1[2111111],su2[2111111]; int main() { int tes; scanf("%d",&tes); while(tes--){ int cnt; scanf("%d%d%d",&l,&cnt,&k); n=0; while(cnt--){ int y,a; scanf("%d%d",&y,&a); for (int i=1;i<=a;i++)x[++n]=y; } k=min(k,n); n1=n2=0; for (int i=1;i<=n;i++) if(x[i]*2<l)a1[++n1]=x[i]; else a2[++n2]=l-x[i]; sort(a1+1,a1+1+n1); sort(a2+1,a2+1+n2); su1[0]=su2[0]=0; for (int i=1;i<=n1;i++) { if(i<=k)su1[i]=a1[i]; else su1[i]=a1[i]+su1[i-k]; //cout<<su1[i]<<endl; } for (int i=1;i<=n2;i++) { if(i<=k)su2[i]=a2[i]; else su2[i]=a2[i]+su2[i-k];//取第i个苹果所需要走的步数,su2[i-k]上一回取得时候所走的步数 //cout<<su2[i]<<endl; } ans=(su1[n1]+su2[n2])*2; //cout<<ans<<endl; for (int i=0;i<=n1 && i<=k;i++){//暴力从a2搜到了两侧都包含,再到全a1,找了最小的 int lef=n1-i,rig=max(0,n2-(k-i)); ans=min(ans,l+(su1[lef]+su2[rig])*2); } printf("%lld\n",ans); } return 0; }
E:状压dp
F:http://acm.hdu.edu.cn/showproblem.php?pid=5305
题意:给你n个人,这n个人构成m对朋友,现在想要这n个人每个人都拥有相等的线上朋友和线下朋友,问能不能实现,如果不能输出0,否则输出有几种方式
思路:dfs搜索,分别假设第i对朋友是线上朋友,要努力保证线上朋友和线下朋友相等,以此类推,直到最后一个,如果这m对都满足,那么sum++,最后的sum就是所要求的结果
代码:
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <cstdio> #include <iomanip> #include <queue> #include <ctime> #include <vector> #include <ctype.h> #define maxn 1005 #define ll long long #define INF 999999999 using namespace std; struct Edge { int a,b; }e[35]; int n,m,f[10],up[10],dw[10]; int ans; void dfs(int u) { if(u==m) { ans++; return; } int a,b; a=e[u].a; b=e[u].b; //cout<<a<<" "<<b<<endl; f[a]--; f[b]--; up[a]++; up[b]++; if((f[a]&&f[b])||(!f[a]&& f[b] && up[a]==dw[a])||(!f[b] && f[a] && up[b]==dw[b])||(!f[a]&& !f[b] && up[a]==dw[a] && up[b]==dw[b])) { dfs(u+1); } up[a]--; up[b]--; dw[a]++; dw[b]++; if((f[a]&&f[b])||(!f[a] && f[b] && up[a]==dw[a])||(!f[b]&& f[a] && up[b]==dw[b])||(!f[a]&& !f[b]&& up[a]==dw[a] && up[b]==dw[b])) { dfs(u+1); } dw[a]--; dw[b]--; f[a]++; f[b]++; } int main() { int t,k; cin>>t; while(t--) { cin>>n>>m; memset(f,0,sizeof (f)); memset(up,0,sizeof(up)); memset(dw,0,sizeof(dw)); ans=0,k=1; for(int i=0;i<m;i++) { cin>>e[i].a>>e[i].b; f[e[i].a]++; f[e[i].b]++; } for(int i=1;i<=n;i++) { if(f[i]%2!=0) { k=0; break; } } if(k==0) { cout<<0<<endl; } else { dfs(0); cout<<ans<<endl; } } return 0; }
G:暴力线段树,开头听了大神言,小伙伴写了半个多小时,无结果,弃疗、、
H:FFT快速傅氏变换,复变中的傅氏变换都没学明白,对于FFT代码、、
I:http://acm.hdu.edu.cn/showproblem.php?pid=5308
题意:用n个n用+、-、*、/、()这几个符号得到24点
思路:暴力找规律,直接输出
代码:
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<cstdio> using namespace std; int n; int main(){ // freopen("data.in","r",stdin); // freopen("dataa.out","w",stdout); while (scanf("%d",&n)!=EOF){ if (n>=15){ printf("1 + 2\n"); printf("3 + 4\n"); printf("5 + 6\n"); printf("7 + 8\n"); printf("%d + 9\n",n+1); printf("%d / 10\n",n+2); printf("%d / 11\n",n+3); printf("%d / 12\n",n+4); printf("%d / 13\n",n+5); printf("%d * %d\n",n+6,n+7); printf("%d * %d\n",n+8,n+9); printf("%d * %d\n",n+10,n+11); printf("14 - 15\n"); int now=n+13; for (int i=16;i<=n;i++){printf("%d * %d\n",i,now); now++;} printf("%d + %d\n",n+12,now); continue; } if (n>=12){ printf("1 + 2\n"); for (int i=1;i<=n*2-24;i++) printf("%d / %d\n",i*2+1,i*2+2); int num=n*4-46; int now=n+1+n*2-24; if (n!=12){ printf("%d - %d\n",n+1,n+2); now++; for (int i=2;i<=n*2-24;i++){printf("%d - %d\n",now,n+1+i); now++;} } int k1=now; printf("%d - %d\n",num+1,num+2); num+=3; now++; for (int i=num;i<=n;i++){printf("%d * %d\n",i,now); now++;} printf("%d + %d\n",k1,now); continue; } if (n>=10){ printf("1 + 2\n"); for (int i=1;i<=24-n*2;i++) printf("%d / %d\n",1+2*i,2+2*i); printf("%d + %d\n",n+1,n+2); int now=n+26-n*2; for (int i=2;i<=24-n*2;i++) {printf("%d + %d\n",n+1+i,now); now++;} if (n==10) continue; printf("7 - 8\n"); printf("17 * 9\n"); printf("18 * 10\n"); printf("19 * 11\n"); printf("20 + 16\n"); continue; } if (n==9){ printf("1 + 2\n"); printf("3 + 10\n"); printf("4 / 5\n"); printf("6 / 7\n"); printf("8 / 9\n"); printf("11 - 12\n"); printf("15 - 13\n"); printf("16 - 14\n"); continue; } if (n==8){ printf("1 + 2\n"); printf("3 + 9\n"); printf("4 - 5\n"); printf("6 * 11\n"); printf("7 * 12\n"); printf("8 * 13\n"); printf("10 + 14\n"); continue; } if (n==7){ printf("1 * 2\n"); printf("3 / 4\n"); printf("5 + 6\n"); printf("8 - 9\n"); printf("11 / 10\n"); printf("12 * 7\n"); continue; } if (n<=3){printf("-1\n"); continue;} if (n==6){ printf("1 * 2\n"); printf("7 - 3\n"); printf("8 - 4\n"); printf("9 - 5\n"); printf("10 + 6\n"); continue; } if (n==5){ printf("1 / 2\n"); printf("6 / 3\n"); printf("4 - 7\n"); printf("5 * 8\n"); continue; } if (n==4){ printf("1 * 2\n"); printf("3 + 5\n"); printf("4 + 6\n"); continue; } } return 0; }
J:DP弃疗~
相关文章推荐
- USACO——Sorting a Three-Valued Sequence
- 音乐播放器实现功能之—
- 各种排序算法总结
- hdu 1520
- 下雨有感
- 2003 求绝对值
- 快速学习stl中集合set
- [LeetCode] Unique Paths
- hdu2492 Ping pong
- 杭电ACM1282——回文数猜想
- selection-内容选中跟光标移动
- PAINT和WM_ERASEBKGND消息
- new/delete 和malloc/free 的区别一般汇总
- 【Matlab学习笔记】【函数学习】size参数
- [c]sdnuoj1032 二维的dp
- 数据库隔离级别详解
- UI第一课,view视图,label 和一些常用方法
- poj 2686
- PS入门——PS的简单使用
- USACO——Ordered Fractions