0530:Pyon-Pyon River Crossing

問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0530
























DAGの最短経路はDPで簡単に求めることができる。
dp[i行目][左からj番目][1行飛ばしの残り回数]:=最小コスト

#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
#include<algorithm>
 
#define f first
#define s second
#define MAX_N 155
#define INF 1000000000
 
using namespace std;
 
typedef pair<int,int> P;
 
int main(void){
 
  int n,m,k,a,b;
 
  while(cin >> n >> m,n|m){
    vector<P>v[MAX_N];
     
    for(int i=1;i<=n;i++){
      cin >> k;
      for(int j=0;j<k;j++){
    	cin >> a >> b;
   		 v[i].push_back(make_pair(a,b));
      }
    }
 
    int dp[MAX_N][11][80];
 
    for(int i=0;i<MAX_N;i++)
      	for(int j=0;j<11;j++)
  			for(int k=0;k<80;k++)
      			dp[i][j][k]=INF;
 
    for(int i=0;i<11;i++)
      for(int j=0;j<80;j++)
    	dp[0][i][j]=dp[1][i][j]=0;
 
    for(int i=2;i<=n;i++){
      for(int j=0;j<v[i].size();j++){
    	for(int l=m;l>=0;l--){
      		for(int k=0;k<v[i-1].size();k++)
        	dp[i][j][l]=min(dp[i][j][l],dp[i-1][k][l]+(v[i][j].s+v[i-1][k].s)*abs(v[i][j].f-v[i-1][k].f));
      		
      		if(l<m){
        		if(i==2)dp[i][j][l]=0;
        		for(int p=0;p<v[i-2].size();p++)
          			dp[i][j][l]=min(dp[i][j][l],dp[i-2][p][l+1]+(v[i][j].s+v[i-2][p].s)*abs(v[i][j].f-v[i-2][p].f));
      		}
    	}
      }
    }
     
    int ans=INF;
    for(int i=0;i<v[n].size();i++)ans=min(ans,dp[n][i][0]);
    if(m>0)for(int i=0;i<v[n-1].size();i++)ans=min(ans,dp[n-1][i][1]);
 
    cout << ans << endl;
  }
 
  return 0;
}