您的位置:首页 > 其它

模板2

2016-04-10 09:50 316 查看
最小生成树(Prim,Kruskal)

求城市的最小生成树,城市标号是从0到n-1,注意重边和不能构成的情况

const int zui = 1000000000;
int n,m;
int map1[1010][1010];
int lowdist[1010];
int visit[1010];
int sum;
bool flag;

void Prim()
{
int i,j,k;
sum = 0;
memset(visit,0,sizeof(visit));
for(i=0; i<=n-1; i++)
{
lowdist[i] = map1[0][i];
}
visit[0] = 1;
for(i=1; i<n; i++)
{
int min1 = zui;
k = -1;
for(j=0; j<=n-1; j++)
{
if(!visit[j] && lowdist[j] < min1)
{
min1 = lowdist[j];
k = j;
}
}
if(k == -1)
{
flag = false;
return;
}
visit[k] = 1;
sum += lowdist[k];
for(j=0; j<=n-1; j++)
{
if(!visit[j] && map1[k][j] < lowdist[j])
{
lowdist[j] = map1[k][j];
}
}
}
}

int main()
{
int i,j;
while(scanf("%d%d",&n,&m) != EOF)
{
int a,b,c;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
map1[i][j] = zui;
}
}
for(i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
if(c < map1[a])//注意重边
{
map1[a][b] = map1[b][a] = c;
}
}
flag = true;//注意这里刚开始是true
Prim();
if(flag)
{
printf("%d\n\n",sum);
}
else
{
printf("impossible\n\n");
}
}
return 0;
}


求城市的最小生成树,修成的路用1标记,没有修成的用0标记

const int inf = 0x7f7f7f7f;//2139062143
typedef long long ll;
using namespace std;

struct node
{
int a,b;
int value;
}road[5000];

int pre[110];

bool cmp(node a,node b)
{
return a.value < b.value;
}

int find(int x)
{
return x == pre[x] ? x : pre[x] = find(pre[x]);
}

int Kruskal(int sum1)
{
int sum = 0;
for(int i=0; i<sum1; i++)
{
int a = find(road[i].a);
int b = find(road[i].b);
if(a != b)
{
pre[a] = b;
sum += road[i].value;
}
}
return sum;
}

int main()
{
int n;
while(scanf("%d",&n) && n)//城市的个数
{
int sum1 = n*(n-1)/2;
int sum = 0;
int a,b,c,d;
for(int i=1; i<=n; i++)
{
pre[i] = i;
}
for(int i=0; i<sum1; i++)//路的个数
{
scanf("%d%d%d%d",&a,&b,&c,&d);
road[i].a = a;
road[i].b = b;
road[i].value = c;
if(d == 1)
road[i].value = 0;
}
sort(road,road+sum1,cmp);
sum = Kruskal(sum1);
printf("%d\n",sum);
}
return 0;
}


最短路径

void Dijkstra()
{
int i,j,k;
int max2;
memset(visit,0,sizeof(visit));
for(i=1; i<=n; i++)
{
low[i] = map1[0][i];
}
for(i=1; i<=n; i++)//每次并一个点,需要并n次
{
max2 = zui;
for(j=1; j<=n; j++)
{
if(!visit[j] && low[j] < max2)
{
k = j;
max2 = low[j];
}
}
visit[k] = 1;
for(j=1; j<=n; j++)
{
if(!visit[j] && low[k] + map1[k][j] < low[j])
{
low[j] = low[k] + map1[k][j];
}
}
}
}

void Floyed()
{
int i,j,k;
for(k=1; k<=n; k++)
{
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
if(map1[i][j] > map1[i][k] + map1[k][j])
{
map1[i][j] = map1[i][k] + map1[k][j];
}
}
}
}
}


二分图的最大匹配(最大匹配数=最大点覆盖)

#include<stdio.h>
#include<string.h>
int lol[101][301],visit[301],cf[301],n;
bool find(int l)
{
int i;
for(i=1; i<=n; i++)
{
if(lol[l][i] && !visit[i])//有好感并且没尝试把妹子许配给别人,要是visit[i]等于1表明,前面有一个人要i这个妹子要定了
{
visit[i] = 1;//表明i这个妹子l要定了,别人不能再娶了,不然下面一条语句腾妹子的过程,本来想让i这个妹子的丈夫重娶一个妹子,结果这个妹子的丈夫还是娶了她,然后又把这个妹子配给l,这就太扯淡了,所以这一句不能放在if语句里面
if(!cf[i] || find(cf[i]))//i这个妹子没丈夫或者能让她的丈夫重娶一个妹子,和这个妹子离婚
{
cf[i] = l;//妹子i的丈夫就是l了
return true;//光棍l摆脱单身
}
}
}
return false;
}
int main()
{
int t,p,i,j,sum,a,sum1;
scanf("%d",&t);
while(t--)
{
memset(lol,0,sizeof(lol));
memset(cf,0,sizeof(cf));
sum1 = 0;
scanf("%d%d",&p,&n);
for(i=1; i<=p; i++)
{
scanf("%d",&sum);//有好感的人的个数
for(j=0; j<sum; j++)
{
scanf("%d",&a);
lol[i][a] = 1;
}
}
for(i=1; i<=p; i++)
{
memset(visit,0,sizeof(visit));//visit每尝试一次就得把visit清零一次
if(find(i))
sum1++;
}
if(p == sum1)//能否都结婚
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
记忆化搜索





AC代码1:

dp[x][y]记录的是点(x,y)到点(n-1,n-1)的数量,dp[x][y]的数量可以由它所到达的点的dp[x][y]的和求出来

[b][cpp]
 view
plain copy

#include <iostream>  

#include<cstring>  

#include<cstdio>  

  

using namespace std;  

  

int map[40][40];  

long long dp[40][40];//用long long 类型  

int dir[2][2] = {{1,0},{0,1}};  

int n;  

  

long long dfs(int x,int y)//返回值是long long 类型  

{  

    int newx,newy,i;  

    if(dp[x][y] || !map[x][y])//map[x][y]为0时,肯定没有到点(n-1,n-1)的路径,直接返回dp[x][y],此时dp[x][y]为0  

        return dp[x][y];  

    for(i=0; i<2; i++)  

    {  

        newx = x + dir[i][0] * map[x][y];  

        newy = y + dir[i][1] * map[x][y];  

        if(newx >= 0 && newy >= 0 && newx < n && newy < n)//判断条件写清楚  

            dp[x][y] += dfs(newx,newy);  

    }  

    return dp[x][y];  

}  

int main()  

{  

    int i,j;  

    char lol[35];  

    while(cin>>n && n != -1)  

    {  

        memset(dp,0,sizeof(dp));  

        for(i=0; i<n; i++)  

        {  

            cin>>lol;  

            for(j=0; j<n; j++)  

            {  

                map[i][j] = lol[j] - '0';  

            }  

        }  

        dp[n-1][n-1] = 1;  

        //printf("%I64d\n",dfs(0,0));  

        cout<<dfs(0,0)<<endl;  

  

    }  

    return 0;  

}  

AC代码2:

[cpp] view
plain copy

#include <iostream>  

#include<cstring>  

  

using namespace std;  

  

int map[40][40];  

long long dp[40][40];//用long long 类型  

int dir[2][2] = {{1,0},{0,1}};  

  

int main()  

{  

    int i,j,n;  

    char lol[35];  

    while(cin>>n && n != -1)  

    {  

        memset(dp,0,sizeof(dp));  

        for(i=0; i<n; i++)  

        {  

            cin>>lol;  

            for(j=0; j<n; j++)  

            {  

                map[i][j] = lol[j] - '0';  

            }  

        }  

        dp[0][0] = 1;  

        for(i=0; i<n; i++)  

        {  

            for(j=0; j<n; j++)  

            {  

                if(!map[i][j] || !dp[i][j])  

                {  

                       continue;  

                }  

                if(i + map[i][j] < n)  

                    dp[i+map[i][j]][j] += dp[i][j];  

                if(j + map[i][j] < n)  

                    dp[i][j+map[i][j]] += dp[i][j];  

            }  

        }  

        cout<<dp[n-1][n-1]<<endl;  

    }  

    return 0;  

}  

BFS

从起始位置到终止位置,转弯次数不超过k

#include<iostream>
#include<queue>
#include<cstring>

using namespace std;

int visit[110][110];
char map[110][110];
int dir[4][2] = {{-1,0,},{1,0},{0,-1},{0,1}};
int m,n,k,endi,endj;

struct node
{
int x;
int y;
int dir;
}a[10010];
bool check(int x,int y)
{
if(x>0 && y>0 && x<=m && y<=n && map[x][y] != '*')//为*的位置不能走
return true;
return false;
}
void bfs(int x,int y)
{
if(x == endi && y == endj)
{
cout<<"yes"<<endl;
return;
}
int i,newx,newy;
queue<node> q;
node in,out;
in.x = x;
in.y = y;
in.dir = -1;
q.push(in);
while(!q.empty())
{
out = q.front();
q.pop();
for(i=0; i<4; i++)
{
newx = out.x + dir[i][0];
newy = out.y + dir[i][1];
while(check(newx,newy))
{
if(!visit[newx][newy])
{
in.x = newx;
in.y = newy;
in.dir = out.dir + 1;
q.push(in);
visit[newx][newy] = 1;
if(newx == endi && newy == endj && in.dir <= k)
{
cout<<"yes"<<endl;
return;
}
}
newx += dir[i][0];
newy += dir[i][1];
}
}
}
cout<<"no"<<endl;
}
int main()
{
int t,i,j,x1,y1;
cin>>t;
while(t--)
{
memset(visit,0,sizeof(visit));
cin>>m>>n;
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
cin>>map[i][j];
}
}
cin>>k>>y1>>x1>>endj>>endi;//最多转弯的次数,起始和终止位置
bfs(x1,y1);
}
return 0;
}


连连看

线的转弯次数不超过2次

#include<stdio.h>
#include<string.h>
int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
int x1,y1,x2,y2,m,n,mark,l = 0;
int a[1010][1010],visit[1010][1010];
void dfs(int x3,int y3,int sum,int direction)
{
int i;
if(x3 < 1 || x3 > n || y3 < 1 || y3 > m || visit[x3][y3] == 1)
return;
if(mark)
return;
if(sum > 2)
return;
if(x3 == x2 && y3 == y2)
{
mark = 1;
return;
}
if(a[x3][y3] != 0)
return;
visit[x3][y3] = 1;
//printf("%d %d %d %d %d\n",l,x3,y3,m,n);
for(i=0; i<4; i++)
{
if(direction != i)
dfs(x3+dir[i][0],y3+dir[i][1],sum+1,i);
else
dfs(x3+dir[i][0],y3+dir[i][1],sum,i);
}
visit[x3][y3] = 0;
}
int main()
{
int i,j,q;
//freopen("input6.txt","r",stdin);
while(scanf("%d%d",&n,&m))
{
if( n == 0 && m == 0)
break;
for(i=1; i<=n; i++)
{
for(j=1; j<=m; j++)
{
scanf("%d",&a[i][j]);
}
}
scanf("%d",&q);
while(q--)
{
mark = 0;
memset(visit,0,sizeof(visit));
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(a[x1][y1] == a[x2][y2] && a[x1][y1] != 0 && (x1 !=x2 || y1 != y2))//0表示空格,即使都是零,也不能消去
{
visit[x1][y1] = 1;
for(i=0; i<4; i++)
{
dfs(x1+dir[i][0],y1+dir[i][1],0,i);
}
}
if(mark == 1)
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}

路劲输出

定义一个二维数组: 
int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};


它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

Input

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output

左上角到右下角的最短路径,格式如样例所示。
Sample Input
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)


int map1[5][5];
int visit[30][30];
int pre[30];

struct node
{
int x;
int y;
}a[30];

int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};

bool judge(int x,int y)
{
if(x >=0 && x < 5 && y >= 0 && y < 5 && !visit[x][y] && !map1[x][y])
return true;
return false;
}

void print(int x)
{
int t = pre[x];
if(t == -1)
{
printf("(0, 0)\n");
return;
}
print(t);
printf("(%d, %d)\n",a[x].x,a[x].y);
}

void bfs()
{
int head = 0,tail = 1;
a[0].x = 0;
a[0].y = 0;
pre[0] = -1;
while(head < tail)
{
for(int i=0; i<4; i++)
{
int newx = a[head].x + dir[i][0];
int newy = a[head].y + dir[i][1];
if(a[head].x == 4 && a[head].y == 4)
{
print(head);
return;
}
if(judge(newx,newy))
{
visit[newx][newy] = 1;
pre[tail] = head;
a[tail].x = newx;
a[tail].y = newy;
tail++;
}
}
head++;
}
}

int main()
{
for(int i=0; i<5; i++)
{
for(int j=0; j<5; j++)
{
scanf("%d",&map1[i][j]);
}
}
memset(visit,0,sizeof(visit));
bfs();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: