AC1
Problem,求用N张邮票且只有K种的情况下可以取得的最大连续值
思路
使用DFS+DP的做法,在DFS中搜索每一位的取值,在DP中去搜索在这个取值的情况下能够取到的最大的最大连续数,并以此+1作为下一个数的上界,
代码部分
0 数据结构
int ans[20]; // 是我们最终的
int a[20];
1 DP
int dp(int t)
{
int f[N];
f[0] = 0;
for (int i = 1; i <= a[t]*n; i++) f[i] = N;
// 赋一个比较大的数取给f[i]
for (int i = 1; i <= t; i++)
{
for (int j = a[i]; j <= a[t]*n; j++)
{
f[j] = min(f[j],f[j-a[i]]+1);
}
}
for (int i = 1; i <= a[t]*n; i++)
{
if(f[i]>n) return i-1;
}
return a[t]*n;
// 取得一个可能的结果
}
DFS
void DFS(int t,int mx)
{
if(t==k+1)
{
// 如果已经查找完了所有的数,那么进行答案的更新
if(mx > maxn)
{
maxn = mx;
// 更新最大值
for (int i = 1; i <= t-1; i++) ans[i] = a[i];
}
return;
}
for (int i = a[t-1] + 1; i <= mx + 1 ; i++)
{
// 通过dp我们可以得到在mx之前的数都是连续可取的,所以我们的下界是a[t-1]+1.上界是mx+1
a[t] = i;
int x = dp(t);
DFS(t+1, x);
// 去搜索下一个数
}
}
ALL
#include<iostream>
#define N 50010
using namespace std;
int n,maxn;
int k;
int ans[20];
int a[20];
int dp(int t)
{
int f[N];
f[0] = 0;
for (int i = 1; i <= a[t]*n; i++) f[i] = N;
// 赋一个比较大的数取给f[i]
for (int i = 1; i <= t; i++)
{
for (int j = a[i]; j <= a[t]*n; j++)
{
f[j] = min(f[j],f[j-a[i]]+1);
}
}
for (int i = 1; i <= a[t]*n; i++)
{
if(f[i]>n) return i-1;
}
return a[t]*n;
// 取得一个可能的结果
}
// 进行Dp去查找每个可能的结果,如果这个数可以在有限的数内被取到,那么就是可行的
void DFS(int t,int mx)
{
if(t==k+1)
{
// 如果已经查找完了所有的数,那么进行答案的更新
if(mx > maxn)
{
maxn = mx;
// 更新最大值
for (int i = 1; i <= t-1; i++) ans[i] = a[i];
}
return;
}
for (int i = a[t-1] + 1; i <= mx + 1 ; i++)
{
// 通过dp我们可以得到在mx之前的数都是连续可取的,所以我们的下界是a[t-1]+1.上界是mx+1
a[t] = i;
int x = dp(t);
DFS(t+1, x);
// 去搜索下一个数
}
}
int main()
{
scanf("%d%d",&n,&k);
DFS(1,0);
for (int i = 1; i <= k; i++)
{
printf("%d ",ans[i]);
}
printf("\n");
printf("MAX=%d",maxn);
return 0;
}
AC2
Problem,单源最短路径
思路
在这里我们使用狄杰斯特拉算法,
What is dijkstra?
从起点出发,不断向外拓展,更新它相邻的点距离的,每次更新再将更新后的点加入到集合中去。
The Code
#include<iostream>
#include<string.h>
#include<queue>
#define N 500010
#define INF 1515870810
using namespace std;
struct egde
{
int dis;
int next;
int to;
}E[N];
// 标准邻接表
struct node
{
int dis,num;
inline bool operator < (const node&x)const
{
return dis>x.dis;
}
};
// 大根堆,使用大根堆堆dijkstra进行优化
int cnt;
int n,m,s,vis[N],dis[N];
int Head[N];
void add(int x,int y,int z)
{
E[++cnt].next = Head[x];
E[cnt].to = y;
E[cnt].dis = z;
Head[x] = cnt;
}
// 增加我们的边
priority_queue<node>q;
void dijkstra()
{
dis[s] = 0;
q.push((node){0,s});
while (!q.empty())
{
node x = q.top();
q.pop();
int temp = x.num;
if(vis[temp]) continue;
vis[temp] = 1;
for (int i = Head[temp]; i; i = E[i].next)
{
int v = E[i].to;
if(dis[v] > E[i].dis + dis[temp])
{
dis[v] = E[i].dis + dis[temp];
q.push((node){dis[v],v});
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
int u,v,w;
memset(dis,INF,sizeof(dis));
for (int i = 0; i < m; i++)
{
scanf("%d%d%d",&u,&v,&w);
if(u!=v)
add(u,v,w);
}
dijkstra();
for (int i = 1; i <= n; i++)
{
if(dis[i]==INF) printf("%d ",2147483647);
else printf("%d ",dis[i]);
}
return 0;
}
AC3
Problem,有向图单源最短路径加上多源同终点最短路径
思路
单源最短路径我们可以继续使用dijkstra算法进行处理,在多源同终点最短路径中我们可以使用反向建图的方式,转化为单源最短路径的方式进行处理
Code
#include<iostream>
#include<string.h>
#include<queue>
#define N 500010
#define INF 1515870810
using namespace std;
struct egde
{
int dis;
int next;
int to;
}E[N];
// 标准邻接表
struct node
{
int dis,num;
inline bool operator < (const node&x)const
{
return dis>x.dis;
}
};
// 大根堆,使用大根堆堆dijkstra进行优化
int cnt;
int n,m,vis[N],dis[N];
int Head[N];
void add(int x,int y,int z)
{
E[++cnt].next = Head[x];
E[cnt].to = y;
E[cnt].dis = z;
Head[x] = cnt;
}
// 增加我们的边
priority_queue<node>q;
void dijkstra(int s)
{
memset(dis,INF,sizeof(dis));
dis[s] = 0;
q.push((node){0,s});
while (!q.empty())
{
node x = q.top();
q.pop();
int temp = x.num;
if(vis[temp]) continue;
vis[temp] = 1;
for (int i = Head[temp]; i; i = E[i].next)
{
int v = E[i].to;
if(dis[v] > E[i].dis + dis[temp])
{
dis[v] = E[i].dis + dis[temp];
q.push((node){dis[v],v});
}
}
}
}
// 标准狄杰斯特拉算法
int main()
{
scanf("%d%d",&n,&m);
int u,v,w;
for (int i = 0; i < m; i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v+n, u+n, w);
// 反向建图
}
dijkstra(1);
long long ans = 0;
for (int i = 2; i <= n; i++)
{
ans += dis[i];
}
dijkstra(1+n);
// 反向单源最短路径
for (int i = 2+n; i <= 2*n; i++)
{
ans += dis[i];
}
printf("%lld",ans);
return 0;
}