您的位置:首页 > 移动开发

Gym 101246E Kidnapping 递推or dfs 优化

2017-04-23 20:49 106 查看
题目链接

题意:

抓劫匪的题,最后总结为有n条路,a[x][y]表示第x条路与第y条路之间的距离,由于绑匪将人绑着,所以人只能计算出走的路程给出计算的路程问最后到达的劫匪窝点可能是那条街(每次都是从第一条路开始)

思路:

这个题的话可以有两种写法,一个是递推,即从这一步可以走的点开始,按照距离去寻找可以走到的下一个点并标记,在赋值回来依次递推,直到最后所有被标记的点就是可能的点.

#include<bits/stdc++.h>
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 100000007
#define inf 0x3f3f3f3f
#define exp 0.00000001
#define pii pair<int, int>
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
int n,m;
int r[222],mp[222][222];
int vis[222],book[222];
set<int>vt;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
Ri(n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
Ri(mp[i][j]);
}
int k,l;
Ri(k);
CLR(vis,0);
CLR(book,0);
vis[1]=1;
for(int i=1;i<=k;i++)
{
Ri(l);
for(int j=1;j<=n;j++)
{
if(vis[j])
{
for(int cc=1;cc<=n;cc++)
{
if(mp[j][cc]==l)
book[cc]=1;
}
}
}
for(int j=1;j<=n;j++)
vis[j]=book[j];
CLR(book,0);
}
for(int i=1;i<=n;i++)
{
if(vis[i])
vt.insert(i);
}
set<int>::iterator it;
cout<<vt.size()<<endl;
for(it=vt.begin();it!=vt.end();it++)
{
cout<<*it<<' ';
}
cout<<endl;
return 0;
}第二种做法也是比较好想的做法的话就是dfs,但是n个点都可以重复走的
所以复杂度为 (n-1)的k次方,明显会炸,这时候就需要我们来一点优化,我们可以想到 将每次的n个点抽象为一个集合,那么这样的集合就有k个了,依次为第一步的集合...一直到第k步的集合,那么对于相同的一步ki我们这个点重复走到的话是没有任何意义的依次来优化,开一个二维数组表示第k步走到的第i个点,并标记.复杂度就变为了n*k
,
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
int mp[1111][1111],vis[222][222];
int n,k,a;
set<int>vt;
int ru[1111],num;
string s;
void dfs(int tt,int ss)
{
if(ss==k+1)
{
vt.insert(tt);
return ;
}
for(int i=1;i<=n;i++)
{
if(mp[tt][i]==ru[ss]&&vis[i][ss]==0)
{
vis[i][ss]=1;
dfs(i,ss+1);
}
}
return ;
}
int main()
{
freopen("Input.txt","r",stdin);
freopen("Output.txt","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&mp[j][i]);
}
}
vt.clear();
scanf("%d",&k);
for(int i=1;i<=k;i++)
scanf("%d",&ru[i]);
memset(vis,0,sizeof(vis));
dfs(1,1);
printf("%d\n",vt.size());
set<int>::iterator it;
for(it=vt.begin();it!=vt.end();it++)
{
printf("%d ",*it);
}
cout<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: