目录
第一步,二维转一维(此步仅为方便,可以省略)
第二步,建边(啥都行,只要死不了)
第三部,bfs(你要dfs也行)
第一步
第二步
第三步
可C+A呢?
剪枝(vis数组登场了!)
总结
A+C记录:又要戳我!
结语:
我的第二道网络流二十四题
链接:戳我
题目大致意思放一下
给你一个N*N零一方阵,你在(1,1),可以沿着边走。当你往左上走的时候,要付B元。你的体力是K,
也就是说每走K条边就要停下来。如果当前节点(不论你还能走多少条边)是1,需付A元钱将体力补满;
你也可以在0的节点付A+C(注意有个A,我当年37分就是卡在这里)元钱将体力补满。问到达(N,N)
需要多少钱
第一步,二维转一维(此步仅为方便,可以省略)
第二步,建边(啥都行,只要死不了)
第三部,bfs(你要dfs也行)
下面正式开始
第一步
首先,先写一个函数,我把它叫做 kks(请见谅)
输入 与
返回对应下标。
就像这样
int kks(int x,int y){
return (x-1)*(n)+y;
}
接着,就可以愉快的开一维了!
第二步
这一步谁都会,直接把配套代码放出来了(我写了个链式前向星)
struct edge{
int v,nxt,w;
void it(int av,int anxt,int aw){
v=av,nxt=anxt,w=aw;
}
}e[N*4];
int h[N],cnt;
void addE(int u,int v){
e[++cnt].it(v,h[u],((v<u)?b:0));
h[u]=cnt;
}
int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
bool hf(int abc){
if(abc>0&&abc<=n)
return 1;
return 0;
}
for(int x=1;x<=n;x++)
for(int y=1;y<=n;y++)
for(int i=0;i<4;i++){
int xx=dx[i]+x,yy=dy[i]+y;
if(hf(xx)&&hf(yy))
addE(kks(x,y),kks(xx,yy));
}
第三步
重点来了!
我在建立边的时候,加入了边权,的问题解决了
同时,我把输入的01矩阵写进了一个叫的数组里
那么,A也解决了
可C+A呢?
按照正常思路,每一次都要枚举一遍,明显容易超时
但是,细细研究就会发现,只要在油量为0的时候加一下(这就是贪心思想,没有死到临头就依然放纵)
并且,同一个地方,一辆车不可能到2次(肯定不是最优解)
因此,建的油箱我们可以不计入讨论
剪枝(vis数组登场了!)
- 在到达同一地点时,油量相同时花钱越少越好
- 在到达同一地点时,油量更多时花钱越少越好
- 剪枝要在C+A与A之前,因为你多费点钱加油还不如不加呢
总结
到此为止,基本思路框架已经出现,接着就是代码了(很乱,见谅)
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k,a,b,c;
const int N=10407;
struct edge{
int v,nxt,w;
void it(int av,int anxt,int aw){
v=av,nxt=anxt,w=aw;
}
}e[N*4];
int h[N],cnt,need[N],ans=0x3f3f3f3f;
int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
int kks(int x,int y){
return (x-1)*(n)+y;
}
bool hf(int abc){
if(abc>0&&abc<=n)
return 1;
return 0;
}
void addE(int u,int v){
e[++cnt].it(v,h[u],((v<u)?b:0));
h[u]=cnt;
}
int vis[N][17];
struct p{
int x,o,pr;
p(int ax,int ao,int apr){x=ax;o=ao;pr=apr;}
bool operator>(const p b) const{
if(pr!=b.pr)
return pr>b.pr;
return o<b.o;
}
};
void bfs(){
memset(vis,0x3f,sizeof vis);
priority_queue<p,vector<p>,greater<p>> pq;
pq.push(p(kks(1,1),k,0));
while(!pq.empty()){
p now=pq.top();
pq.pop();
int x=now.x,o=now.o,pr=now.pr;
//cout<<x<<" "<<o<<" "<<pr<<endl;
int flg=0;
if(x==kks(n,n)){
ans=min(ans,pr);
continue;
}
for(int i=o;i<=k;i++)
if(vis[x][i]<=pr)
flg=1;
if(flg)
continue;
vis[x][o]=pr;
if(need[x]&&o!=k)
o=k,pr+=a;
if(o==0)
pr+=c+a,o=k;
for(int i=h[x];i;i=e[i].nxt)
pq.push(p(e[i].v,o-1,pr+e[i].w));
}
}
signed main(){
scanf("%lld%lld%lld%lld%lld",&n,&k,&a,&b,&c);
for(int i=1;i<=n;i++)
for(int j=1,ck;j<=n;j++){
scanf("%lld",&ck);
if(ck)
need[kks(i,j)]=1;
}
for(int x=1;x<=n;x++)
for(int y=1;y<=n;y++)
for(int i=0;i<4;i++){
int xx=dx[i]+x,yy=dy[i]+y;
if(hf(xx)&&hf(yy))
addE(kks(x,y),kks(xx,yy));
}
bfs();
printf("%lld",ans);
}
A+C记录:又要戳我!
结语:
这题可以作为网络流二十四题的入门题
最后,祝您端午节快乐!
冒泡排序,选择排序,插入排序,快速排序,堆排序,归并排序,希尔排序,桶排序,基数排序,端午节帮您排忧解难。
有向图,无向图,有环图,无环图,完全图,稠密图,稀疏图,拓扑图祝您端午节宏图大展。
最长路,最短路,单源路径,所有节点对路径,祝您新年路路通畅。
二叉树,红黑树,van Emde Boas树,最小生成树祝您端午节好运枝繁叶茂。
最大流,网络流,标准输入流,标准输出流,文件输入流,文件输出流,祝您端午节顺顺溜溜。
线性动规,区间动规,坐标动规,背包动规,树型动归为您的端午节规划精彩。
散列表,哈希表,邻接表,双向链表,循环链表帮您在端午节表达喜悦。
O(n!), O(2^n), O(n^3), O(n^2), O(nlog n), O(n), O(log n), O(1), 祝您端午节渐进步步高!