Noip 2009 解题报告(潜伏着,Hankson的趣味题,最优贸易,靶形数独)
来源:互联网 发布:python win32api 编辑:程序博客网 时间:2024/06/05 13:22
校内赛,模拟Noip2009的题目。刚刚接到则个题目,我是很慌的。
不多说了直接正题。
由于题目被我搞掉了,所以只写解法吧。。。
第一题
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>using namespace std;const int N=100;const int M=26;char s1[N+5],s2[N+5],s3[N+5];int len1,len2,len3;int map[M+1];int main(){ freopen("spy.in","r",stdin); freopen("spy.out","w",stdout); memset(map,-1,sizeof(map)); scanf("%s",s1); scanf("%s",s2); scanf("%s",s3); len1=strlen(s1),len2=strlen(s2),len3=strlen(s3); for(int i=0;i<=len1-1;i++) { if(map[s1[i]-'A']!=-1&&map[s1[i]-'A']!=s2[i]-'A') { printf("Failed"); return 0; } map[s1[i]-'A']=s2[i]-'A'; } for(int i=0;i<=24;i++) for(int j=i+1;j<=25;j++) if(map[i]==map[j]) { printf("Failed"); return 0; } for(int i=0;i<=25;i++) if(map[i]==-1) { printf("Failed"); return 0; } for(int i=0;i<=len3-1;i++) printf("%c",map[s3[i]-'A']+'A'); return 0;}
这个就是我程序。好像过不完因为有点问题。。有一种情况无法判断。。将就看吧。
第二题
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>using namespace std;int n,a0,a1,b0,b1,ans;int gcd(int x,int y){ return y==0?x:gcd(y,x%y);}int lcm(int x,int y){ return x/gcd(x,y)*y;}bool judge(int x){ if(gcd(x,a0)!=a1)return 0; if(lcm(x,b0)!=b1)return 0; return 1;}int main(){ freopen("son.in","r",stdin); freopen("son.out","w",stdout); scanf("%d",&n); while(n--) { int ans=0; scanf("%d%d%d%d",&a0,&a1,&b0,&b1); for(int i=1;i*i<=b1;i++) { if(b1%i==0) { if(judge(i)==1)ans++; if(i*i!=b1) if(judge(b1/i)==1) ans++; } } printf("%d\n",ans); } return 0;}
这道题就是普通的水题,但是注意只用循环到根号就可以。
第三题
这道题是我为数不多的能够AC得图论的题,其思路非常简洁明了:就是用两次广搜(或者说是SPFA)。第一次我们从头到尾更新出最小的点权,第二次我们从尾到头更新出最大的点权。再将路过每个点时所经过的最大最小点权的两个数组一一枚举,找到最大差值就可以了。
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>using namespace std;const int M=500000;const int N=100000;int n,m;int head1[N+5],head2[N+5],num=0;int w[N];int minn[N+5],maxn[N+5];struct edge{ int next1,next2,u,v; edge(){next1=-1;next2=-1;}};struct edge ed[2*M+5];//临界表 void build(int u,int v){ num++; ed[num].u=u; ed[num].v=v; ed[num].next1=head1[u]; head1[u]=num; ed[num].next2=head2[v]; head2[v]=num;}//建表,相当于两张,分别是相反方向的两条路径 void bfs1(){ int front=0,rear=1; int state[N],flag[N]; memset(flag,0,sizeof(flag)); memset(minn,0x7f,sizeof(minn)); state[rear]=1,minn[1]=w[1],flag[1]=1; do { front++; int u=state[front]; flag[u]=0; for(int i=head1[u];i!=-1;i=ed[i].next1) { int v=ed[i].v; if(minn[v]>minn[u]||w[v]<minn[v]) { minn[v]=min(w[v],minn[u]); if(flag[v]==0)state[++rear]=v; flag[v]=1; } } }while(front<rear);}//只要可以到达,就把最小的值赋成最小的值 void bfs2(){ int front=0,rear=1; int state[N],flag[N]; memset(flag,0,sizeof(flag)); memset(maxn,-1,sizeof(maxn)); state[rear]=n,maxn[n]=w[n],flag[n]=1; do { front++; int u=state[front]; for(int i=head2[u];i!=-1;i=ed[i].next2) { int v=ed[i].u; if(maxn[u]>maxn[v]||w[v]>maxn[v]) { maxn[v]=max(w[v],maxn[u]); if(flag[v]==0)state[++rear]=v; flag[v]=1; } } flag[u]=0; }while(front<rear);}//只要可以到达,就把最大的值赋成最大的值, //但是是从n向起点1逆向寻找 int main(){ freopen("trade.in","r",stdin); freopen("trade.out","w",stdout); memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<=m;i++) { int u,v,k; scanf("%d%d%d",&u,&v,&k); if(k==1)build(u,v); if(k==2) { build(u,v); build(v,u); } }//建表 bfs1(); bfs2(); int ans=0; for(int i=1;i<=n;i++) ans=max(ans,maxn[i]-minn[i]);//最大差值 printf("%d",ans); return 0;}
第四题
原本想要深度优先搜索,结果发现代码有点复杂,而且不好处理。后来想到贪心,就是尽可能多的去填填的多的格子,发现自己又不太可能实现。但只用搜索的话注定会超时,所以我们还需要位运算。下面我们看一看大神的代码:
#include<iostream>#include<cstdlib>#include<cstdio>#include<algorithm>#include<iostream>#include<cmath>using namespace std;const int mlen=10;int a[mlen][mlen],b[mlen][mlen];int row[mlen],lie[mlen],line[mlen],ma[mlen];int f[512],ans,node[mlen],cnt[mlen];void init() { for(int i=0;i<9;i++) b[i][0]=b[0][i]=b[8][i]=b[i][8]=6; for(int i=1;i<8;i++) b[i][1]=b[1][i]=b[7][i]=b[i][7]=7; for(int i=2;i<7;i++) b[i][2]=b[2][i]=b[6][i]=b[i][6]=8; for(int i=3;i<6;i++) b[i][3]=b[3][i]=b[5][i]=b[i][5]=9; b[4][4]=10; int t=0; for(int i=1,j=0;i<=511;i<<=1,j++) f[i]=j; for(int i=0;i<9;i++) for(int j=0;j<9;j++) { scanf("%d",&a[i][j]); if(a[i][j]!=0) { row[i]|=1<<j; t=1<<(a[i][j]-1); if((lie[i]&t)||(line[j]&t)||(ma[i/3*3+j/3]&t)) { printf("-1\n"); exit(0); } lie[i]|=t;line[j]|=t; ma[i/3*3+j/3]|=t; } else cnt[i]++; }}void sore() { int nowans=0; for(int i=0;i<9;i++) for(int j=0;j<9;j++) nowans+=a[i][j]*b[i][j]; if(ans<nowans) ans=nowans;}//计算分数 void dfs(int t) { int pos,k; if(t==9) { sore(); return; } int i=node[t]; if(!cnt[i]) { dfs(t+1); return; } cnt[i]--; int p=(511^row[i])&(-(511^row[i])); row[i]|=p; int j=f[p]; pos=511^(lie[i]|line[j]|ma[i/3*3+j/3]); while(pos>0) { k=pos&(-pos);pos^=k; lie[i]|=k;line[j]|=k; ma[i/3*3+j/3]|=k;a[i][j]=f[k]+1; dfs(t); lie[i]^=k;line[j]^=k; ma[i/3*3+j/3]^=k; } cnt[i]++; row[i]^=p;}int main() { freopen("sudoku.in","r",stdin); freopen("sudoku.out","w",stdout); init(); for (int i=0;i<9;i++) node[i]=i; for (int i=0;i<9;i++) for (int j=i+1;j<9;j++) if(cnt[node[i]]>cnt[node[j]]) node[i]^=node[j],node[j]^=node[i],node[i]^=node[j]; int tot=0; while(!cnt[node[tot]]) tot++; dfs(tot); if(!ans) { printf("-1\n"); return 0; } printf("%d\n",ans); return 0;}
至此,本次考试的总结就到这里。
2017 3 10
1 0
- Noip 2009 解题报告(潜伏着,Hankson的趣味题,最优贸易,靶形数独)
- NOIP 2009 解题报告(潜伏者,hankson的趣味题,最有贸易,靶形数独)
- NOIP2009解题报告(C/C++)(潜伏者)(Hankson的趣味题)(最优贸易)(靶形数独)
- NOIP2009 题解 潜伏者 Hankson的趣味题 最优贸易 靶形数独
- NOIP2009 潜伏者 Hankson的趣味题 最优贸易 靶形数独
- [NOIP2009]潜伏者,Hankson's Problem,最优贸易,靶形数独
- 【Noip 2009】 最优贸易 解题报告
- Hankson的趣味题[NOIP2009]解题报告
- Hankson的趣味题 解题报告
- NOIP-2009-B2 HANKSON 的趣味题
- [NOIP 2009提高] Hankson的趣味题
- 【noip】HankSon的趣味题
- NOIp2009TG T2/Luogu P1072 Hankson的趣味题 解题报告
- [NOIP 2009]靶形数独
- NOIP 2009 靶形数独
- NOIP 2009 靶形数独
- NOIP 2009 靶形数独
- 最优贸易解题报告
- 多线程(线程通信)
- 算法训练 数的划分 (动态规划)
- 【剑指offer】面试题10:二进制中1的个数
- Leetcode刷题记——75. Sort Colors(颜色排序)
- 从源码编译MYSQL5.7
- Noip 2009 解题报告(潜伏着,Hankson的趣味题,最优贸易,靶形数独)
- 2016年校招秋招 C++开发 面试问题总结(中兴、CVTE、瑞晟、华为、YY)
- javascript笔记整理系列
- javapoet的认识
- 马虎的算式
- dubbo 简单搭建流程
- Hive复合数据类型array,map,struct的使用
- 重温JavaSE之方法的声明和使用(三)
- EL表达式整数被当作字符串处理