1、for循环中的++i和i++没有区别
for(int i=0;i<n;i++)等价于for(int i=0;i<n;++i)
2、DAG(Directed Acyclic Graph)有向无环图。不包含有向环的有向图。
3、辗转相除法
while(c)
{
c=a%b;
a=b;//最大公约数
b=c;
}
求出最大公约数后,两数相乘除以最大公约数就是最小公倍数。
int gcd(int a,int b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
4、判断线段的重叠
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int s,e;
} a[50005];
int cmp(node x,node y)
{
if(x.s==y.s)
return x.e>y.e;
else
return x.s<y.s;
}
int main()
{
int t;
while(~scanf("%d",&t))
{
int sum=0;
int minn=0,maxn=0;
int ans=0;
for(int i=0; i<t; i++)
scanf("%d %d",&a[i].s,&a[i].e);
sort(a,a+t,cmp);
下面这几行重中之重,其他方法会超时
for(int i=0; i<t; i++)
{
sum=min(maxn,a[i].e)-max(minn,a[i].s);
if(sum>ans)
ans=sum;
minn=min(minn,a[i].s);
maxn=max(maxn,a[i].e);
}
printf("%d\n",ans);
}
return 0;
}
5、排列组合+杨辉三角
注意观察到,可以发现循环的值是;C(n,m)=n!/(m!*(n-m)!),因为n值过大,不可以直接用公式
组合数学的递推公式:C(n,m)=C(n,m-1)+C(n-1,m-1)
#include<cstdio>
#include<cstring>
using namespace std;
int t;
int map[2005][2005];
int n,m;
int c=1007;
int main()
{
memset(map,0,sizeof(map));
for(int i=1; i<2005; i++)
{
map[i][i]=1;
map[i][0]=1;
}
for(int i=2; i<2005; i++)
{
for(int j=1; j<2005; j++)
{
map[i][j]=map[i-1][j-1]%c+map[i-1][j]%c;
}
}
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
printf("%d\n",map[m][n]%c);
}
return 0;
}
6、HDU-1799题解
//这道题利用 排列组合Cn(m)(也就是从n个元素中任取m个元素)的思考方式,实现过程用杨辉三角(因为杨辉三角的值 可以对1007取余并保存)。
//现在解释一下为什么这道题跟排列组合有关:
//假设现在有4个 小球 A B C D 要从中取2个 用排列组合的方式:先取A 然后依次取 B C D ;接下来 取B 然后依次取C D ;接下来取C 只能 取剩下的D 这样就有3 + 2 + 1 = 6 种组合。
//这里的4 就是题目的n 这里的2就是题目的m(循环次数);
//如果 循环次数为3 那么 先取A 再取B 然后依次 取 C D;
//所以题目问的操作次数 也就是 问有多少种取球方式;
7、ZOJ-2723
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
bool visited[1000005];
bool test[1000005];
void prime()
{
memset(visited,false,sizeof(visited));
memset(test,false,sizeof(test));
for(int i=2; i<sqrt(1000005); i++)
{
if(visited[i]==false)
{
for(int j=2; j*i<1000005; j++)
visited[i*j]=true;
}
}
}
int main()
{
int n;
prime();
while(~scanf("%d",&n))
{
int i=2;
int num=0;
记住这个方法,其他会超时
while(n!=1)
{
if(visited[i]==false)
{
while(n%i==0)
{
n=n/i;
num++;
}
}
i++;
}
if(num==2)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
8、SCU-1117
//str的加减
#include<cstring>
#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string str[3005];
int cmp(string x,string y)
{
return x+y>y+x;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
{
cin>>str[i];
}
sort(str,str+n,cmp);
for(int i=0; i<n; i++)
cout<<str[i];
printf("\n");
}
return 0;
}
9、UVA-10815
/*输入一个文本,找出所有不同的单词(连续的字母序列),
按照字典序从小到大输出单词不区分大小写*/
//ps 对于缩写 I'm 去除'后为I和m两个单词
#include<iostream>
#include<string>
#include<set>
using namespace std;
set<string>s;
int main()
{
string str,str1;
while(cin>>str)
{
for(int i=0;i<str.length();i++)
{
if(isalpha(str[i]))//isalpha()判断字符是否为英文字母,若为英文字母,返回非0(小写字母为2,大写字母为1)。若不是字母,返回0
{
str[i]=tolower(str[i]);//tolower()功能是把字母字符转换成小写,非字母字符不做出处理
str1+=str[i];
}
else
{
if(str1.length())
{
s.insert(str1);
str1.clear();
}
}
}
if(str1.length())
{
s.insert(str1);
str1.clear();
}
}
set<string>::iterator it=s.begin();
while(it!=s.end())
{
cout<<*it<<endl;
it++;
}
return 0;
}
10、HDU-1027 问你全排列的第M个排列为多少
//next_permutation()的应用
#include<iostream>
#include<algorithm>
using namespace std;
int data[1005];
void init(int n)
{
for(int i=0;i<=n;i++)
{
data[i]=i+1;
}
}
int main()
{
int N,M;
while(cin>>N>>M)
{
init(N);
int t=0;
do{
if(t==M-1)
{
for(int i=0;i<N;i++)
{
if(i==N-1)
cout<<data[i]<<endl;
else
cout<<data[i]<<" ";
}
break;
}
t++;
}while(next_permutation(data,data+N));
}
}
11、HDU-1285 拓扑排序确定比赛名次
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define N 505
vector<int> v[N];
int Next[N];
int in[N];
int n,m,k;
void tp()
{
k=0;
priority_queue<int,vector<int>,greater<int> >q;
for(int i=1;i<=n;i++)
if(!in[i])
q.push(i);
while(!q.empty())
{
int t=q.top();
q.pop();
Next[k++]=t;
for(int i=0;i<v[t].size();i++)
{
int m=v[t][i];
if(in[m]==1)
q.push(m);
else
in[m]--;
}
}
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
for(int i=0;i<=n;i++)
{
in[i]=0;
v[i].clear();
Next[i]=-0;
}
for(int i=0;i!=m;i++)
{
int a,b;
scanf("%d %d",&a,&b);
v[a].push_back(b);
in[b]++;
}
tp();
for(int i=0;i<k-1;i++)
printf("%d ",Next[i]);
printf("%d\n",Next[k-1]);
}
return 0;
}
12、HDU-3790 最短路径与最少花费问题
#include<stdio.h>
#include<string.h>
#define INF 0x3f3f3f3f
#define Min(a,b) a>b?b:a
struct Node
{
int adj,val;
}g[1005][1005];
int dist[1005];//距离
int value[1005];//费用
int used[1005];//标记
int n,m,i,j;
void Dijkstra(int s)
{
memset(dist,0x3f,sizeof(dist));
memset(value,0x3f,sizeof(value));
memset(used,0,sizeof(used));
dist[s]=0;//从起点开始
value[s]=0;
while(1)
{
int k,u=-1,d[1005];
int min=INF;
memset(d,0,sizeof(d));
for(i=1;i<=n;i++)
if(used[i]==0&&dist[i]<min)//找出从起点到下一个最小距离的顶点
{
min=dist[i];
u=i;//记录下标
}
if(u==-1)//判断所有顶点是否都到达过
return ;
for(i=1,k=0;i<=n;i++)
if(dist[u]==dist[i]&&used[i]==0)
d[k++]=i;//从起点到下一个要访问的顶点的最小距离可能有多个
for(i=0;i<k;i++)
used[d[i]]=1;
for(i=0;i<k;i++)//多个满足的点分别进行迪杰斯特拉最短路查找
for(j=1;j<=n;j++)
if(g[d[i]][j].adj!=INF&&(dist[d[i]]+g[d[i]][j].adj)<=dist[j])
{//原理与 main()函数中建立邻接矩阵一样
if((dist[d[i]]+g[d[i]][j].adj)<dist[j])
value[j]=value[d[i]]+g[d[i]][j].val;
else
value[j]=Min(value[j],value[d[i]]+g[d[i]][j].val);
dist[j]=dist[d[i]]+g[d[i]][j].adj;
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)&&(n||m))
{
int a,b,d,p;
memset(g,0x3f,sizeof(g));
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&a,&b,&d,&p);
if(d<=g[a][b].adj)//处理路径距离问题
{
if(d==g[a][b].adj)//如果距离相等,则存放最少的费用
g[a][b].val=g[b][a].val=Min(p,g[a][b].val);
else//否则,存放新路径距离的费用
g[a][b].val=g[b][a].val=p;
g[a][b].adj=g[b][a].adj=d;//填充路径距离
}
}
int s,t;
scanf("%d%d",&s,&t);
Dijkstra(s);
printf("%d %d\n",dist[t],value[t]);
}
return 0;
}
13、判断是不是一棵树
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int map[100005];
int main()
{
int count=1;
while(1)
{
int j=0;
int i=0;
int flag=0;
int a,b;
memset(map,0,sizeof(map));
while(~scanf("%d %d",&a,&b)&&a&&b)
{
if(a<0||b<0)
return 0;
if(map[b]-1==1)
flag=1;
if(map[a]==0)
j++;
if(map[b]==0)
j++;
map[a]=1;
map[b]=2;
i++;
}
if(flag==0&&j==i+1)
{
printf("Case %d is a tree.\n",count);
count++;
}
else
{
printf("Case %d is not a tree.\n",count);
count++;
}
}
return 0;
}
14、HDU-2544 最短路,送衣服问题
#include<iostream>
#include<cstring>
#define inf 0x3f3f3f3f
#define maxn 205
using namespace std;
int map[maxn][maxn];
int dis[maxn];
int vis[maxn];
int n,m;
void Dijkstra(int s)
{
int min;
vis[s]=1;
for(int i=1; i<=n; i++)
{
if(i!=s)
dis[i]=map[s][i];
}
for(int i=1; i<n; i++)
{
min=inf;
for(int j=1; j<=n; j++)
{
if(!vis[j]&&dis[j]<min)
{
min=dis[j];
s=j;
}
}
vis[s]=1;
for(int j=1; j<=n; j++)
{
if(!vis[j]&&map[s][j]<inf&&(dis[j]>dis[s]+map[s][j]))
dis[j]=dis[s]+map[s][j];
}
}
}
int main()
{
while(~scanf("%d %d",&n,&m)&&n&&m)
{
int a,b,v;
memset(vis,0,sizeof(vis));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(i==j)
map[i][j]=0;
else
map[i][j]=inf;
}
}
for(int i=1; i<=m; i++)
{
scanf("%d %d %d",&a,&b,&v);
if(map[a][b]>v||map[b][a]>v)
map[a][b]=map[b][a]=v;
}
Dijkstra(1);
printf("%d\n",dis[n]);
}
return 0;
}
16、POJ-2421 修路最少花费
题意十分简单粗暴,首行给出N,接着是个N*N的矩阵,map[i][j]就代表i到j的权值。接着给出Q,下面Q行,每行两个数字A,B,代表A到B,B到A的权值为0。最后输出最小生成树的权值和就行。
#include<iostream>
#include<cstring>
#include<algorithm>
#define maxn 600000
int fa[maxn];
int map[105][105];
using namespace std;
struct node
{
int x,y,v;
} tank[maxn];
int cmp(node a,node b)
{
return a.v <b.v ;
}
int find(int x)
{
if(fa[x]==-1)
return x;
return fa[x]=find(fa[x]);
}
int main()
{
int n,m;
int a,b;
while(cin>>n)
{
int sum=0;
int k=0;
memset(fa,-1,sizeof(fa));
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
cin>>map[i][j];
}
cin>>m;
for(int i=1; i<=m; i++)
{
cin>>a>>b;
map[a][b]=map[b][a]=0;
}
for(int i=1; i<=n; i++)
for(int j=i; j<=n; j++)
{
if(i!=j)
{
tank[k].x=i;
tank[k].y=j;
tank[k].v=map[i][j];
k++;
}
}
sort(tank,tank+k,cmp);
for(int i=0; i<k; i++)
{
int fx=find(tank[i].x);
int fy=find(tank[i].y);
if(fx!=fy)
{
fa[fx]=fy;
sum+=tank[i].v;
}
}
cout<<sum<<endl;
}
return 0;
}
17、遍历最大面积
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char map[25][25];
int vis[25][25];
int dir[4][2]= {{-1,0},{0,1},{1,0},{0,-1}};
int w,h;
int dfs(int si,int sj)
{
map[si][sj]='#';
vis[si][sj]=1;
for(int i=0; i<4; i++)
{
int x=si+dir[i][0];
int y=sj+dir[i][1];
if(x<0||x>=h||y<0||y>=w||map[x][y]=='#')
continue;
dfs(x,y);
}
}
int main()
{
while(~scanf("%d%d",&w,&h)&&w&&h)
{
memset(vis,0,sizeof(vis));
for(int i=0; i<h; i++)
scanf("%s",map[i]);
bool flag=false;
for(int i=0; i<h; i++)
{
for(int j=0; j<w; j++)
{
if(map[i][j]=='@')
{
dfs(i,j);
flag=true;
break;
}
}
if(flag)
break;
}
int num=0;
for(int i=0; i<h; i++)
for(int j=0; j<w; j++)
{
if(vis[i][j])
num++;
}
printf("%d\n",num);
}
return 0;
}
18、找组合数,并按字典序输出
#include<cstdio>
#include<cstring>
using namespace std;
bool visited[300];
int map[300];
int temp[11];
int n,k;
int dfs(int num,int sum)
{
if(sum==k)
{
for(int i=0; i<k; i++)
{
printf("%d",map[i]);
if(i<k-1)
printf(" ");
else
{
printf("\n");
}
}
}
else
{
for(int i=num; i<=n; i++)
{
if(visited[i]==false)
{
visited[i]=true;
map[sum]=i;
if(map[sum]>map[sum-1])
{
dfs(i+1,sum+1);
visited[i]=false;
}
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(map,0,sizeof(map));
memset(visited,false,sizeof(visited));
scanf("%d %d",&n,&k);
dfs(1,0);
}
return 0;
}
19、三个杯子分水
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int v[3];
bool visited[105][105][105];
int avg;
struct node
{
int num[3],count;
};
int bfs()
{
node start;
queue<node>q;
start.num[0]=v[0];
start.num[1]=0;
start.num[2]=0;
start.count=0;
visited[start.num[0]][start.num[1]][start.num[2]]=true;
q.push(start);
while(!q.empty() )
{
node mid;
mid=q.front();
q.pop() ;
if(mid.num[2]*2==v[0]&&mid.num[0]*2==v[0]||mid.num[1]*2==v[0]&&mid.num[0]*2==v[0])
return mid.count;
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
{
if(i!=j)
{
int minn=min(v[j]-mid.num[j],mid.num[i]);
node end=mid;
end.num[j]+=minn;
end.num[i]-=minn;
end.count=mid.count+1;
if(visited[end.num[0]][end.num[1]][end.num[2]]==false)
{
q.push(end);
visited[end.num[0]][end.num[1]][end.num[2]]=true;
}
}
}
}
}
return -1;
}
int main()
{
while(~scanf("%d%d%d",&v[0],&v[1],&v[2])&&v[0]&&v[1]&&v[2])
{
memset(visited,false,sizeof(visited));
if(v[0]%2!=0)
printf("NO\n");
else if(v[1]==v[2])
printf("1\n");
else
{
int ans=bfs();
if(ans==-1)
printf("NO\n");
else
printf("%d\n",ans);
}
}
return 0;
}
20、迷宫问题找出口,并将走过的路坐标输出
#include<iostream>
#include<cstdio>
#include<string.h>
#include<queue>
using namespace std;
int map[5][5];
int vis[5][5];
int dir[4][2]={{-1, 0}, {0, -1}, {1, 0}, {0, 1}};//因为是从终点往起点搜,所以按逆时针方向走
struct NODE
{
int x, y, no, next;//结点x, y为坐标,no为该坐标在node[50]数组的下标,next为输出路径时下一个结点的下标
}node[50];
void bfs()
{
int tot = 0;
node[0].x = node[0].y = 4;
node[0].no = node[0].next = 0; //因为要正向输出路径,所以从终点反向往起点搜
queue<NODE> q; //用于保存路径
q.push(node[0]);
vis[4][4] = 1; //标记已经走过的
while(!q.empty())
{
NODE now = q.front();
q.pop();
if (now.x == 0 && now.y == 0)
{ //到起点,则打印路径
int t = now.no;
while(1)
{ //因为node数组中每个结点中都有
printf("(%d, %d)\n", node[t].x, node[t].y);
if (!t)
return;
t = node[t].next;
}
}
for(int i = 0; i < 4; i++)
{
int nx = now.x + dir[i][0];//nx, ny下一节点坐标
int ny = now.y + dir[i][1];
if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5 && !map[nx][ny] && !vis[nx][ny])
{
vis[nx][ny] = 1;//一个节点入队时,标记已经访问,并把该节点信息存入node数组
node[++tot].x = nx;
node[tot].y = ny;
node[tot].no = tot;
node[tot].next = now.no;
q.push(node[tot]);
}
}
}
}
int main()
{
memset(map, 0, sizeof(map));
memset(vis, 0, sizeof(vis));
memset(node, 0, sizeof(node));
while(scanf("%d %d %d %d %d", &map[0][0], &map[0][1], &map[0][2], &map[0][3], &map[0][4])!=EOF)
{
for (int i = 1; i < 5; i++)
for (int j = 0; j < 5; j++)
scanf("%d", &map[i][j]);
bfs();
}
return 0;
}
21、HDU-1181 变形课,检查字符串的首尾字母
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#include<string>
using namespace std;
#define M 1005
int visited[M];
bool flag;
int k;
struct node
{
char x,y;
} arr[M];
void dfs(char x)
{
if(x=='m')
{
flag=true;
return ;
}
else
{
for(int i=0; i<k; i++)
{
if(arr[i].x==x&&!visited[i])
{
visited[i]=1;
dfs(arr[i].y);
visited[i]=0;
}
}
}
return ;
}
int main()
{
string str;
k=0;
while(cin>>str)
{
if(str[0]=='0'&&str.length()==1)
{
memset(visited,0,sizeof(visited));
flag=false;
dfs('b');
k=0;
if(flag)
printf("Yes.\n");
else
printf("No.\n");
}
else
{
arr[k].x=str[0];
arr[k].y=str[str.length()-1];
k++;
}
}
return 0;
}
22、HDU-1253 胜利大逃亡
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int map[55][55][55];
bool visited[55][55][55];
int d[6][3]= {1,0,0,
0,1,0,
0,0,1,
-1,0,0,
0,-1,0,
0,0,-1
};
int sx,sy,sz,ex,ey,ez;
int a,b,c;
int time;
struct node
{
int x,y,z,count;
};
int bfs()
{
node now;
now.x=0;
now.y=0;
now.z=0;
now.count=0;
queue<node>q;
q.push(now);
visited[0][0][0]=true;
while(!q.empty() )
{
now=q.front() ;
q.pop();
for(int i=0; i<6; i++)
{
node end;
end.x=now.x+d[i][0];
end.y=now.y+d[i][1];
end.z=now.z+d[i][2];
end.count=now.count+1;
if(visited[end.x][end.y][end.z]==false&&end.x>=0&&end.y>=0&&end.z>=0&&end.x<a&&end.y<b&&end.z<c&&map[end.x][end.y][end.z]==0)
{
visited[end.x][end.y][end.z]=true;
q.push(end);
if(end.x==a-1&&end.y==b-1&&end.z==c-1)
{
if(end.count<=time)
return end.count;
else
return -1;
}
}
}
}
return -1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(map,0,sizeof(map));
memset(visited,false,sizeof(visited));
scanf("%d%d%d%d",&a,&b,&c,&time);
for(int i=0; i<a; i++)
{
for(int j=0; j<b; j++)
{
for(int k=0; k<c; k++)
{
scanf("%d",&map[i][j][k]);
}
}
}
printf("%d\n",bfs());
}
return 0;
}
23、从所给数字中,选择数字组合成需要的数字,并输出所有的组合可能性
#include<cstdio>
#include<cstring>
using namespace std;
int map[1005];
int num[1005];
bool visited[1005];
int n,m;
int count;
bool flag;
void dfs(int count,int sum)
{
if(sum==m)
{
flag=true;
for(int i=0; i<count; i++)
{
if(visited[i]==true)
{
printf("%d",map[i]);
if(i<count-1)
printf("+");
else
printf("\n");
}
}
}
else
{
for(int i=count; i<n; i++)
{
visited[i]=true;
sum=sum+map[i];
dfs(i+1,sum);
visited[i]=false;
sum=sum-map[i];
while(map[i]==map[i+1])
i++;
}
}
}
int main()
{
while(~scanf("%d%d",&m,&n)&&n&&m)
{
memset(visited,false,sizeof(visited));
for(int i=0; i<n; i++)
scanf("%d",&map[i]);
flag=false;
printf("Sums of %d:\n",m);
dfs(0,0);
if(flag==false)
printf("NONE\n");
}
return 0;
}
24、动态规划的三个核心元素:最优子结构、边界、状态转移方程。
25、memset(map,1,sizeof(map));数据会出现错误,暂时不知道原因
26、HDU 1272 小希的迷宫
并查集查找判断是否形成环,如果形成环,一定不成立。
如果未形成环,再判断顶点数是否等于边数+1;