HDU_Steps9.2 杂题 HDU2052 HDU1871 HDU1254 HDU3350 HDU3234 HDU2642 HDU2833 HDU3483
来源:互联网 发布:c语言中的string.h 编辑:程序博客网 时间:2024/05/16 02:04
HDU2052 Picture
HDU2642 Stars
HDU1871 无题
上面两道纯水题。。为什么Steps做到这中间还有这么水的题=。=
HDU1254 推箱子
推箱子模型,最短路使用DFS加回溯,更新找到箱子的最小值,搜索人可达的位置用BFS,人和箱子的位置共同组成一个状态。
#include<cstdio>#include<string.h>#include<queue>using namespace std;int cas,m,n,sr,sc,er,ec,pr,pc,ans;bool flag;int map[10][10],dvis[10][10][10][10];int dr[]={0,-1,0,1};int dc[]={1,0,-1,0};bool outr(int x){return x<0||x>=m;}bool outc(int x){return x<0||x>=n;}//传入新旧人的位置以及箱子的位置bool bfs(int opr,int opc,int npr,int npc,int a,int b){if(opr==npr&&opc==npc)return true;queue<pair<int,int> > q;int bvis[10][10];memset(bvis,0,sizeof bvis);q.push(make_pair(opr,opc));bvis[opr][opc]=1;while(!q.empty()){int r=q.front().first,c=q.front().second;q.pop();for(int i=0;i<4;i++){int nr=r+dr[i],nc=c+dc[i];if(nr<0||nc<0||nr>=m||nc>=n||bvis[nr][nc])continue;//墙和箱子的位置是不可走的if(map[nr][nc]==1||(nr==a&&nc==b))continue;bvis[nr][nc]=1;if(nr==npr&&nc==npc)return true;q.push(make_pair(nr,nc));}}return false;}void dfs(int obr,int obc,int opr,int opc,int step){//上一步箱子和人的位置,以及走的步数if(step>ans)return;//这里注意剪枝if(obr==er&&obc==ec){ans=min(step,ans);flag=true;//标记成功到达return;}for(int i=0;i<4;i++){//算出新的人和新的箱子的位置int npr=obr+dr[i],npc=obc+dc[i];int nbr=obr+dr[(i+2)%4],nbc=obc+dc[(i+2)%4];if(outr(nbr)||outr(npr)||outc(nbc)||outc(npc))continue;//出界了if(map[nbr][nbc]==1||map[npr][npc]==1)continue;//人或者箱子要去的位置有墙if(!bfs(opr,opc,npr,npc,obr,obc))continue;//人不能走到那个位置if(dvis[npr][npc][nbr][nbc]==1)continue;//已经到达过这个状态dvis[npr][npc][nbr][nbc]=1;dfs(nbr,nbc,npr,npc,step+1);dvis[npr][npc][nbr][nbc]=0;}return;}int main(){scanf("%d",&cas);while(cas--){scanf("%d%d",&m,&n);for(int i=0;i<m;i++){for(int j=0;j<n;j++){scanf("%d",&map[i][j]);if(map[i][j]==2)sr=i,sc=j;if(map[i][j]==4)pr=i,pc=j;if(map[i][j]==3)er=i,ec=j;}}flag=false;ans=10000000;memset(dvis,0,sizeof dvis);dfs(sr,sc,pr,pc,0);//传入箱子和人的位置if(flag==false){printf("-1\n");}else{printf("%d\n",ans);}}return 0;}
HDU3350 #define is unsafe
给定一个只含有MAX和+操作的式子,求加法运行了多少次,其中MAX使用宏定义。注意一个规律,对于MAX(A,B)其中A中加a次,B中加b次若A>B,则加a*2+b次,否则a+b*2次。然后用递归处理这个字符串就可以了。
#include<cstdio>#include<string>#include<iostream>using namespace std;struct state{state(int a,int b){s=a,k=b;}int s,k;//和,次数};state find(string str){int in=0,len=str.length(),num=0;//当前位置,字符串长度if(str[in]>='0'&&str[in]<='9'){//第一个字母是整数,读取这个数while(in<len&&str[in]>='0'&&str[in]<='9')num=num*10+str[in++]-'0';if(in>=len)return state(num,0);//如果只剩一个数,直接返回else{//只能是a+B的形式,B是一个式子,处理B段state st=find(str.substr(in+1));return state(num+st.s,st.k+1);}}else if(str[in]=='M'){in+=4;int cnt=1,mid=0;while(cnt>0){//匹配MAX()右括号的位置,并找出对应这个MAX的逗号的位置if(str[in]=='(')cnt++;else if(str[in]==')')cnt--;if(str[in]==','&&cnt==1)mid=in;in++;}state le=find(str.substr(4,mid-4));//求MAX(A,B)中的Astate ri=find(str.substr(mid+1,in-mid-2));//求MAX(A,B)中的Bint p1,p2;if(le.s>ri.s){p1=le.s;p2=le.k*2+ri.k;}else{p1=ri.s;p2=le.k+ri.k*2;}if(in>=len-1){//已经到达末端return state(p1,p2);}else{//MAX(A,B) + C的形式,求Cstate st=find(str.substr(in+1));//处理加号后面的部分return state(p1+st.s,st.k+p2+1);}} }int main(){int cas;char str[1005];cin>>cas;while(cas--){cin>>str;state rs=find(str);cout<<rs.s<<" "<<rs.k<<endl;}return 0;}
HDU3234 Exclusive-OR
这题并查集真恶心啊。。首先a^a=0,a^0=a,虚拟一个父节点,将所有已知的连接到这个父节点上来,用一个数组记录该节点异或父节点的值,最后如果是偶数个则父节点被异或偶数次,不影响结果,如果为奇数次并且父节点不是虚拟节点的话就无法得到答案了。如果在同一个集合中但是结果与当前值冲突就是wrong了~
#include<cstdio>#include<string.h>#include<algorithm>using namespace std;int n,q;int p[20005],va[20005],map[20005];void init(int x){ for(int i=0;i<=x;i++){ p[i]=i; va[i]=0; } }int find(int x){ int t=p[x]; if(x!=p[x]){ p[x]=find(p[x]); va[x]^=va[t];//x^p[x]=va[x],p[x]^p[px]=va[p[x]],所以x^p[p[x]]=va[x]^va[p[x]] } return p[x]; }bool merge(int x,int y,int v){ int px=find(x); int py=find(y); if(px==py){ if((va[x]^va[y])!=v)return false; return true; } if(px==n)swap(px,py);//n为虚拟节点,已知的都连到n上 p[px]=py; //x^px=va[x],y^py=va[y],x^py=v; //所以px^py=va[x]^va[y]^v va[px]=va[x]^va[y]^v; p[px]=py; return true;}int main(){ char op,s[1000],cas=1;int a[20]; while(scanf("%d%d",&n,&q),n||q){ gets(s); init(n+1); printf("Case %d:\n",cas++); int nqs=0,tmpas,num; bool right=true; while(q--){ gets(s); tmpas=0,num=0; op=s[0]; //不正确就可以结束了 if(!right)continue; int len=strlen(s); for(int i=2;i<len;i++){//输入数字,数字数量不确定 if(s[i]>='0'&&s[i]<='9')num=num*10+s[i]-'0'; else{ a[tmpas++]=num; num=0; } } a[tmpas++]=num; if(op=='I'&&tmpas==2){//I p v,p和n合并 right=merge(a[0],n,a[1]); nqs++; }else if(op=='I'&&tmpas>2){ right=merge(a[0],a[1],a[2]); nqs++; }else if(op=='Q'){ int ans=0; memset(map,0,sizeof map); for(int i=1;i<tmpas;i++){//a^a=0这种直接排除 map[find(a[i])]++; ans=(ans^va[a[i]]); } bool f=1; for(int i=1;i<tmpas;i++){ int t=find(a[i]); if(map[t]%2!=0&&t!=n){//假设x和y的和都是t,x^t^y^t=t^y,t被抵消掉,但如果奇数次,t未知并且未被抵消就不能得到答案 printf("I don't know.\n"); f=0; break; } } if(f){ printf("%d\n",ans); } } if(!right){ printf("The first %d facts are conflicting.\n",nqs); } } printf("\n"); } return 0; }
HDU2642 Stars
裸的二维树状数组加上简单的容斥原理
#include<cstdio>#include<string.h>#include<algorithm>using namespace std;int c[1002][1002];bool v[1002][1002];int lowbit(int x){return x&(-x);}void modify(int x,int y,int p){for(int i=x;i<=1001;i+=lowbit(i)){for(int j=y;j<=1001;j+=lowbit(j)){c[i][j]+=p;}}}int sum(int x,int y){int s=0;for(int i=x;i>0;i-=lowbit(i)){for(int j=y;j>0;j-=lowbit(j)){s+=c[i][j];}}return s;}int main(){int m,x1,x2,y1,y2;char op[3];while(scanf("%d",&m)!=EOF){memset(v,false,sizeof v);memset(c,0,sizeof c);while(m--){scanf("%s",op);if(op[0]=='B'){scanf("%d%d",&x1,&x2);x1++,x2++;if(v[x1][x2])continue;v[x1][x2]=true;modify(x1,x2,1);}else if(op[0]=='D'){scanf("%d%d",&x1,&x2);x1++,x2++;if(!v[x1][x2])continue;v[x1][x2]=false;modify(x1,x2,-1);}else{scanf("%d%d%d%d",&x1,&x2,&y1,&y2);x1++,x2++,y1++,y2++;if(x1>x2)swap(x1,x2);if(y1>y2)swap(y1,y2);printf("%d\n",sum(x2,y2)+sum(x1-1,y1-1)-sum(x1-1,y2)-sum(x2,y1-1));}}}return 0;}
HDU2833 WuKong
好题,求两条最短路中最多能公共几个点。首先容易证明公共最短路必然连续,然后用floyd求出每两点之间的最短路。如果d[st][en]=d[st][i]+d[i][j]+d[j][en],说明d[i][j]是最短路的一部分。c[i][j]代表两点之间最短路的条数。
#include<cstdio>#include<algorithm>using namespace std;const int inf=200000000;int d[305][305],c[305][305];//有一个性质,如果有公共最短路,则公共最短路一定是连续的(可以用反证法证明)//Floyd后,如果i和j在最短路上则有d[s][e]=d[s][i]+d[i][j]+d[j][e]int main(){int n,m,u,v,w,s1,s2,t1,t2;while(scanf("%d%d",&n,&m),n||m){for(int i=0;i<=n;i++){for(int j=0;j<=n;j++){d[i][j]=(i==j)?0:inf;c[i][j]=0;}}for(int i=0;i<m;i++){scanf("%d%d%d",&u,&v,&w);if(d[u][v]<w)continue;d[u][v]=d[v][u]=w;c[u][v]=c[v][u]=1;}scanf("%d%d%d%d",&s1,&t1,&s2,&t2);//Folyd,其中c[i][j]表示两点间最短路的条数最大有多少条for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(d[i][j]>d[i][k]+d[k][j]){d[i][j]=d[i][k]+d[k][j];c[i][j]=c[i][k]+c[k][j];}if(d[i][j]==d[i][k]+d[k][j]&&c[i][j]<c[i][k]+c[k][j]){c[i][j]=c[i][k]+c[k][j];}}}}//DPint rs=-1;//可能只有一个交点;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(d[s1][i]+d[i][j]+d[j][t1]==d[s1][t1]&&d[s2][i]+d[i][j]+d[j][t2]==d[s2][t2]){rs=max(rs,c[i][j]);}}}printf("%d\n",rs+1);}return 0;}
HDU3483 A Very Simple Problem
求sigma(x^k*k^x),k<2*1e9,x<50,又是一道恶心的构造矩阵,解释在注释中
#include<cstdio>#include<string.h>using namespace std;/*求sum(x^k*k^x) k=1~N * x^(k+1)*(k+1)^x=x^k*x*(k+1)^x 然后用二项式定理展开(k+1)^x即可 * 例如当x=4时 * | 1x 0 0 0 0 0 | |x^k*k^0| |x^(k+1)*(k+1)^0| * | 1x 1x 0 0 0 0 | |x^k*k^1| |x^(k+1)*(k+1)^1| * | 1x 2x 1x 0 0 0 |*|x^k*k^2|=|x^(k+1)*(k+1)^2| * | 1x 3x 3x 1x 0 0 | |x^k*k^3| |x^(k+1)*(k+1)^3| * | 1x 4x 6x 4x 1x 0 | |x^k*k^4| |x^(k+1)*(k+1)^4| * | 1x 4x 6x 4x 1x 1x | | S(k) | | S(k+1) | */typedef __int64 ll;const int maxn=55;ll c[maxn][maxn],n,m,x;void init(){//初始化二项式系数memset(c,0,sizeof c);for(int i=1;i<maxn;i++){c[i][1]=c[i][i]=1;for(int j=2;j<=i-1;j++){c[i][j]=c[i-1][j-1]+c[i-1][j];if(c[i][j]>=m)c[i][j]%=m;}}}struct mat{ll a[maxn][maxn];mat(int type){//0是全0矩阵,2是单位矩阵,1是构造的矩阵memset(a,0,sizeof a);if(type==0)return;if(type==2){for(int i=0;i<x+2;i++)a[i][i]=1;return;}for(int i=0;i<x+2;i++){for(int j=0;j<=i;j++){if(i!=x+1){a[i][j]=c[i+1][j+1]*x;if(a[i][j]>=m)a[i][j]%=m;}else a[i][j]=a[i-1][j];}}a[x+1][x+1]=1;}mat mult(mat b){mat rs(0);for(int i=0;i<x+2;i++){for(int j=0;j<x+2;j++){for(int k=0;k<x+2;k++){rs.a[i][j]=rs.a[i][j]+a[i][k]*b.a[k][j];if(rs.a[i][j]>=m)rs.a[i][j]%=m;}}}return rs;}int getr(){ll r=0;for(int i=0;i<x+2;i++){r+=x*a[x+1][i];}return r%m;}};mat binMat(int k){//非递归的二分求解矩阵,递归栈溢出mat m(1),tmp(2);while(k){if(k&1)tmp=tmp.mult(m);m=m.mult(m);k>>=1;}return tmp;}int main(){while(scanf("%I64d%I64d%I64d",&n,&x,&m)){if(n==-1)break;init();mat m=binMat(n-1);printf("%d\n",m.getr());}return 0;}
- HDU_Steps9.2 杂题 HDU2052 HDU1871 HDU1254 HDU3350 HDU3234 HDU2642 HDU2833 HDU3483
- hdu1871
- hdu2833
- hdu2052
- HDU2052
- hdu2052
- hdu2642
- HDU2052
- hdu1254
- hdu1254
- HDU1254
- hdu1871 无题
- hdu2833 WuKong
- WuKong-HDU2833
- hdu2052 Picture
- HDU2052(预处理)
- HDU2052 Picture
- HDU2052 Picture
- c#编写QQ群发器源码
- 水波纹屏保原理
- Ubuntu 文件名与mp3标签乱码解决方法
- 广播机制
- #pragma 用法
- HDU_Steps9.2 杂题 HDU2052 HDU1871 HDU1254 HDU3350 HDU3234 HDU2642 HDU2833 HDU3483
- 购物车
- win7+eclipse indigo+phpeclipse使得eclipse无法创建java类的解决方法
- spring源码学习笔记-初始化(六)-完成及异常处理
- c++虚函数表详解(四)
- Spring Acegi Security实例解析三
- JSP隐式对象和MVC设计模式
- 不知道哪里错了?请大家帮忙……
- C 语言中互不相同随机数的应用研究