刚开始用dp做一直不过,想不通。
看了别人报告才知道,dp没有解决后效性,即当前的决策会对下一次travel。
出不了数据,但觉得数据大的时候应该会错
这类k次操作,每次操作代价都不同,求最大或者最小代价的问题,只能用费用流
http://hi.baidu.com/graphis/item/74b8afc6ec27f870f6c95d50从多进程动态规划到费用流的转化,这里讲的很好
dp也不是不行,但你要记录之前决策的状态,比如这可能要记录到第k次操作时每个格子被取过了没
边=(容量,代价)
s到起始点建边(k,0),终点到t建边(k,0)
每个点拆点,u->u1 建边 (1,cost) , (k-1,0)
u能转移到v : u1->v : (k,0)
题目还可以变化为,第一次取的代价是多少,第二次去的代价是多少,第三次……做法只要在u->u1 建多几条边 (1,cost) (1,cost) (1,cost)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <map> #include <set> #include <algorithm> #include <ctime> #include <vector> #include <string> #include <queue> using namespace std; #define N 5500 #define M 55000 struct Edge { int v,cost,cap; }edge[M]; int adj[M],head[N],e,n,k,src,dest; int d[N],pre[N],vis[N]; bool spfa() { queue<int>q; memset(d,-1,sizeof(d)); memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); q.push(src); d[src]=0; vis[src]=1; while(!q.empty()) { int u=q.front();q.pop();vis[u]=0; for(int i=head[u];i!=-1;i=adj[i]) if(edge[i].cap && d[edge[i].v] < d[u] + edge[i].cost) { d[edge[i].v]=d[u]+edge[i].cost; pre[edge[i].v]=i; // 这里错了!! //if(edge[i].v==dest) //return true; if(!vis[edge[i].v]) { vis[edge[i].v]=1; q.push(edge[i].v); } } } if(pre[dest]!=-1) return true; else return false; } int cost_flow() { int ans=0; while(spfa()) { int u=dest; int f=N*3000; while(pre[u]!=-1) { f=min(f,edge[pre[u]].cap); u=edge[pre[u]^1].v; } u=dest; while(pre[u]!=-1) { ans+=edge[pre[u]].cost; edge[pre[u]].cap-=1; edge[pre[u]^1].cap+=1; u=edge[pre[u]^1].v; } } return ans; } void addedge(int u,int v,int cap,int cost) { edge[e].v=v;edge[e].cap=cap;edge[e].cost=cost; adj[e]=head[u];head[u]=e++; edge[e].v=u;edge[e].cap=0;edge[e].cost=-cost; adj[e]=head[v];head[v]=e++; } int main () { scanf("%d%d",&n,&k); memset(head,-1,sizeof(head)); e=0; src=2*n*n+1; dest=2*n*n+2; int u; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { scanf("%d",&u); addedge((i-1)*n+j,n*n+(i-1)*n+j,1,u); addedge((i-1)*n+j,n*n+(i-1)*n+j,k-1,0); if(i-1>0) addedge(n*n+(i-2)*n+j,(i-1)*n+j,k,0); if(j-1>0) addedge(n*n+(i-1)*n+j-1,(i-1)*n+j,k,0); } addedge(src,1,k,0); addedge(2*n*n,dest,k,0); int ans=cost_flow(); printf("%d\n",ans); return 0; }