tEST 1 for NOIP 2017.9.9.
来源:互联网 发布:淘宝新开店铺 编辑:程序博客网 时间:2024/06/07 01:06
头更大
这个9月完就要去集训搞NOIP了。。。
9月30天也就3次测试。。。为防万一我还是每次测试玩都写个总结。。
补进度来的,上周有点浪。
第一题苟住,第二题第三题GG
Function(100/100)
题目背景
SOURCE:NOIP2015-SHY-6
题目描述
对于一个整数,定义 f(x) 为他的每个数位的阶乘的乘积。例如 f(135)=1! * 3! * 5! = 720。给出一个数 a(可以包含前缀零),a 满足他的至少一个数位大于 1 。我们要求出最大的整数 x ,其中 x 不含 0 或 1 ,并且满足 f(a) = f(x)。
输入格式
第一行一个整数 n ,表示 a 的长度。
接下来一个整数 a 。
输出格式
一行一个整数 x 表示答案。
样例数据 1
输入 [复制]
4
1234
输出
33222
样例数据 2
输入 [复制]
2
03
输出
3
备注
【样例1说明】
1! * 2! * 3! * 4! = 3! * 3! * 2! * 2! * 2!
【样例2说明】
0! * 3! = 3!
【数据范围】
对 30% 的输入数据 :n≤2
对 100% 的输入数据 :n≤15
暴力枚举多想即可。
MY/STD.CPP
#include<iostream>#include<iomanip>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<string>#include<algorithm>#include<queue>using namespace std;int n,stk[60];long long hh;int cnt = 0;void get(int n){ switch(n) { case 2: stk[++cnt]=2; break; case 3: stk[++cnt]=3; break; case 4: stk[++cnt]=2;stk[++cnt]=2;stk[++cnt]=3; break; case 5: stk[++cnt]=5; break; case 6: stk[++cnt]=3;stk[++cnt]=5; break; case 7: stk[++cnt]=7; break; case 8: stk[++cnt]=2;stk[++cnt]=2;stk[++cnt]=2;stk[++cnt]=7; break; case 9: stk[++cnt]=2;stk[++cnt]=3;stk[++cnt]=3;stk[++cnt]=7; break; }}int main(){ cin >> n; cin >> hh; while(hh) { int jud = hh%10; if(jud!=0&&jud!=1)get(jud); hh/=10; } sort(stk+1,stk+cnt+1); for(int i=cnt;i>=1;i--)cout<<stk[i]; return 0;}
Box
题目背景
SOURCE:NOIP2015-SHY-6
题目描述
有个桌子长 R 宽 C ,被分为 R*C 个小方格。其中,一些方格上有箱子,一些方格上有按钮,一些方格上有障碍物,一些方格上是空地。现在有个任务,需要把所有箱子推到这些按钮上面。箱子有个特征,只能推不能搬不能拉。现在需要用最少的步数把所有箱子推到按钮上。
当然,箱子和人都只能以格子为单位移动,不存在一部分在格内一部分在格外的情况;只能向四个方向推,箱子和推箱子的队员都不能穿越障碍物。推动的定义是,人的前进方向被箱子挡住,且箱子在顺着前进方向的下一格不是箱子或者障碍物,那么就可以推着箱子和箱子一起前进一步。
输入格式
输入第一行有两个整数 R,C(4<=R,C<=7),代表桌子的长和宽,接下来一共有 R 行,每行有 C 个字符。
字符的含义:
0:代表空地
1:代表障碍物
2:代表箱子
3:代表按钮
4:人所在的初始地方
输入数据保证障碍物环绕整个地图,箱子数目跟按钮数目相同,箱子最少有一个,不会超过 3 个,队员肯定只有一个。不用考虑箱子初始就按着按钮的情况。保证有解。
输出格式
输出只有一行,为解决机关的最小步数。
样例数据 1
输入 [复制]
4 5
11111
14231
10231
11111
输出
4
备注
【样例说明】
在样例中,最快的方法之一是先向东把第一个箱子推到按钮上,然后向西走回原处,之后向南一步,再向东推第二个箱子到按钮上。至此任务完成,共使用了 4 步。
【数据范围】
对 30% 的输入数据 :箱子只有一个。
对 100% 的输入数据 :4<=R,C<=7。
一开始我怎么也觉得不可能用Dp应该用搜索才可能搞定像推箱子这样的题。。后来发现我错的离谱。。Dp大法好。。
虽然我到现在都还没看怎么懂orz。
STD.CPP
#include<iostream> #include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<ctime>#include<cctype>#include<queue>using namespace std;int D[5][3],len,a[4],R[64][3],v[4],tot,n,m,A[8][8],f[50][50][50][50],pos[7][7],c[6000001][4];bool b[9][9];char sl[9];int main(){ //freopen("box.in","r",stdin); //freopen("box.out","w",stdout); cin>>n>>m; int sx,sy; D[1][1]=1; D[1][2]=0; D[2][1]=-1; D[2][2]=0; D[3][1]=0; D[3][2]=1; D[4][1]=0; D[4][2]=-1; len=0; tot=0; int cnt=0; memset(R,0,sizeof(R)); memset(a,0,sizeof(a)); memset(v,0,sizeof(v)); for(int i=1;i<=n;i++) { scanf("%s",sl); for(int j=1;j<=m;j++) { pos[i][j]=++cnt; R[cnt][1]=i; R[cnt][2]=j; A[i][j]=sl[j-1]-'0'; if(A[i][j]==4) sx=i,sy=j,A[i][j]=0; if(A[i][j]==2) a[++len]=pos[i][j]; if(A[i][j]==3) v[++tot]=pos[i][j]; } } memset(f,255,sizeof(f)); f[pos[sx][sy]][a[1]][a[2]][a[3]]=0; c[1][0]=pos[sx][sy]; c[1][1]=a[1]; c[1][2]=a[2]; c[1][3]=a[3]; memset(b,true,sizeof(b)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(A[i][j]==1) b[i][j]=false; for(int k=1,l=1;l<=k;l++) { int ren=c[l][0],xiang1=c[l][1],xiang2=c[l][2],xiang3=c[l][3],xren=R[ren][1],yren=R[ren][2],x1=R[xiang1][1],y1=R[xiang1][2]; int x2=R[xiang2][1],y2=R[xiang2][2],x3=R[xiang3][1],y3=R[xiang3][2]; b[x1][y1]=false; b[x2][y2]=false; b[x3][y3]=false; int ssx=f[ren][xiang1][xiang2][xiang3]; if(xiang1==v[1]&&xiang2==v[2]&&xiang3==v[3]) { cout<<f[ren][xiang1][xiang2][xiang3]; return 0; } for(int i=1;i<=4;i++) if(1<=xren+D[i][1]&&xren+D[i][1]<=n&&1<=yren+D[i][2]&&yren+D[i][2]<=m) { if(b[xren+D[i][1]][yren+D[i][2]]&&f[pos[xren+D[i][1]][yren+D[i][2]]][xiang1][xiang2][xiang3]==-1) { f[pos[xren+D[i][1]][yren+D[i][2]]][xiang1][xiang2][xiang3]=ssx+1; c[++k][0]=pos[xren+D[i][1]][yren+D[i][2]]; c[k][1]=xiang1; c[k][2]=xiang2; c[k][3]=xiang3; } int q[4]; q[1]=xiang1; q[2]=xiang2; q[3]=xiang3; if(pos[xren+D[i][1]][yren+D[i][2]]==q[2])swap(q[1],q[2]); if(pos[xren+D[i][1]][yren+D[i][2]]==q[3])swap(q[1],q[3]); if(pos[xren+D[i][1]][yren+D[i][2]]==q[1]) if(1<=xren+2*D[i][1]&&xren+2*D[i][1]<=n&&1<=yren+2*D[i][2]&&yren+2*D[i][2]<=m&&b[xren+2*D[i][1]][yren+2*D[i][2]]) { q[1]=pos[xren+2*D[i][1]][yren+2*D[i][2]]; for(int j=1;j<=3;j++) for(int k=j+1;k<=3;k++) if(q[k]!=0&&q[k]<q[j]) swap(q[j],q[k]); if(f[pos[xren+D[i][1]][yren+D[i][2]]][q[1]][q[2]][q[3]]==-1) { f[pos[xren+D[i][1]][yren+D[i][2]]][q[1]][q[2]][q[3]]=ssx+1; c[++k][0]=pos[xren+D[i][1]][yren+D[i][2]]; c[k][1]=q[1]; c[k][2]=q[2]; c[k][3]=q[3]; } } } b[x1][y1]=true; b[x2][y2]=true; b[x3][x3]=true; } cout<<"17"; return 0;}
Tree
题目背景
SOURCE:NOIP2015-SHY-6
题目描述
给你一个有 N 个点 M 条边的无向带权连通图,每条边是白色或黑色,求一颗最小权的恰好有 K 条白边的生成树。
输入格式
第一行三个数 N、M、K ,分别表示点数、边数和所需的白边数。
接下来 M 行,每行四个数 u、v、w、c ,分别表示一条边的两个端点(从0开始标号)、边权和颜色(0表示白色,1表示黑色)。
输入数据保证有解。
输出格式
一行一个数表示所求生成树的边权和。
样例数据 1
输入 [复制]
2 2 1
0 1 1 1
0 1 2 0
输出
2
备注
【数据范围】
对 20% 的输入数据 :1≤N≤15。
对 100% 的输入数据 :1≤N≤50000,1≤M≤100000, 1≤w≤100。
貌似听大神讲过的一道原题。。。然而下来好像没懂就没管了。
论学一样懂一样的重要性。
二分大法好orz。
STD.CPP
#include<iostream>#include<cstdio>#include<cstdlib>#include<ctime>#include<cmath>#include<cstring>#include<string>#include<algorithm>using namespace std;int n,m,k,a,b,d,e,l,r=0,mid,cnt,cntt;int fa[50005];long long sum;struct node { int u,v,w,c;}edge[100005],bian[100005];bool cmp(node a,node b){ if(a.w==b.w) return a.c<b.c; return a.w<b.w;}int getfa(int x){ if(fa[x]==x) return x; fa[x]=getfa(fa[x]); return fa[x];}inline bool check(int mid) { for(int i=1;i<=m;++i) { bian[i]=edge[i]; if(!edge[i].c) bian[i].w = edge[i].w + mid; } cnt=0,cntt=0,sum=0; for(int i=0;i<n;++i) fa[i]=i; sort(bian+1,bian+m+1,cmp); for(int i=1;i<=m;++i) { a=getfa(bian[i].u); b=getfa(bian[i].v); if(a!=b) { fa[a] = b; cnt++; if(!bian[i].c) { cntt++; sum += bian[i].w; } else sum+=bian[i].w; if(cnt==n-1) break; } } return (cntt >= k);}int main(){ cin>>n>>m>>k; for(int i=1;i<=m;++i) { cin>>a>>b>>d>>e; edge[i].u=a; edge[i].v=b; edge[i].w=d; edge[i].c=e; } r=150; l=-r; while (l+1<r) { mid=(l+r)/2; if (check(mid)) l=mid; else r=mid; } check(l);cout << sum-k*l; return 0;}
感想
T1现在能(变)苟(简)住(单)了。。T2,T3的暴力还要学学,打得好暴力,定能出奇迹
还有要补补二分和Dp了。。
- tEST 1 for NOIP 2017.9.9.
- *TEST 1 for NOIP
- Test 1 for NOIP: Result for Day1
- Test 1 for NOIP: Result for Day2
- Test 5 for NOIP
- Test 7 for NOIP
- Test 6 for NOIP
- Test 10 for NOIP
- tEST 2 for NOIP
- tEST 3 for NOIP
- *TEST 5 for NOIP 。。。
- *TEST 6 for NOIP + NOIP初赛
- -TEST Fin 1 for NOIP 垃圾电脑(300-300)
- Test 2 for NOIP- Result for Day1
- Test 2 for NOIP- Result for Day2
- Test 3 for NOIP- Result for Day2
- Test 4 for NOIP- Result for Day1
- Test 4 for NOIP- Result for Day2
- ThinkPHP3.2中所有的单字母方法
- 博客专家申请规则
- hdu5289单调队列
- MATLAB安装libsvm常见问题
- 【洛谷】P1582倒水
- tEST 1 for NOIP 2017.9.9.
- 1032 链表
- leetcode 171. Excel Sheet Column Number(C语言)
- 数据库学习——聚合函数
- 系统学习C++(4)
- Fiddler Script 优化
- Cointainer With Most Water
- hdu5289ST表+二分
- shell流程控制