树状dp , 看了两个牛人的博客 看了各种思路 , 输入输出很难处理,也看懂了一些方法。
临接表用vector处理,虽然有点慢,写起来能方便一点。
然后还用到了stringstream 和map
最后是状态的转移方程 dp[v][j+k] = min (dp[v][j]+dp[u][k],dp[v][j+k])
然后最后还要dp[v][sum] = min (dp[v][sum] , value[v])
把这个部分和上面合并也行 但是注意value[v]的数值可能会影响到原来的dp
这样的话 就需要初始化 将原来的dp保存起来。
补充一点: 注意各种初始化.. 初始化写错了 很坑爹的。
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
const int MAXN = 205;
const int INF = 0xffffff;
char str[1000];
char name[MAXN];
int dp[MAXN][MAXN];
int v[MAXN];
int vis[MAXN];
int index;
vector < int > adj [MAXN];
int n ,m;
int dfs ( int r )
{
vis[r] = 1;
int num = 1;
dp[r][0] = 0;
for ( int i = 1 ; i <= n; i ++ )
dp[r][i] = INF;
for ( int i = 0 ; i < adj[r].size(); i ++ )
{
int to = adj[r][i];
if ( vis[to] ) continue;
num += dfs ( to );
for ( int j = num ; j > 0 ; j -- )
for ( int k = 1 ; j - k >= 0 ; k ++ )
{
if ( dp[r][j] > dp[r][j-k] + dp[to][k] )
dp[r][j] = dp[r][j-k] + dp[to][k];
}
}
if ( dp[r][num] > v[r] )
dp[r][num] = v[r];
return num;
}
int main()
{
while ( gets( str ) && str[0] != '#' )
{
map < string , int > ma;
sscanf(str, "%d%d" , &n , &m );
//cout << n << m << endl;
index = 1;
ma.clear();
for ( int i = 0 ; i <= n ;i ++ )
adj[i].clear();
memset ( vis , 0 , sizeof ( vis ));
for ( int i = 0 ; i < n ; i ++ )
{
int w;
scanf("%s%d" , name , &w );
if ( ma.find ( name ) == ma.end() )
ma[name] = index++;
//cout << "name ==== " << name << endl;
int root = ma[name];
//cout << root << endl;
v[root] = w;
gets(str);
stringstream ss (str);
while ( ss >> name )
{
//cout << "name ==== " << name << endl;
if ( ma.find (name) == ma.end () )
ma[name] = index++;
int leaf = ma[name];
//cout << "leaf == " << leaf << endl;
//adj[leaf].push_back( root );
adj[root].push_back( leaf );
if ( !vis[leaf] )
vis[leaf] = 1;
}
}
//cout <<"***********" << endl;
//cout << vis [3] << endl;
for ( int i = 1 ; i <= n ; i ++ )
{
if ( !vis[i] )
adj[0].push_back( i );
}
memset ( vis , 0 ,sizeof ( vis ));
dp[0][0] = 0;
v[0] = INF;
for ( int i = 1 ; i <= n; i ++ )
dp[0][i] = INF;
dfs ( 0 );
int ans = INF;
for ( int i = m ; i <= n; i++)
if (dp[0][i] < ans)
ans = dp[0][i];
// for ( int i = 0 ; i <= n ; i ++)
// for ( int j = 0 ; j < adj[i].size() ; j ++ )
// printf("%d ===== %d ==== %d\n" , i , j , adj[i][j] );
// for ( int i = 0 ; i <= n ; i ++ )
// for ( int j = 0 ; j <= n ; j ++ )
// printf("dp[%d][%d] = %d\n" , i , j , dp[i][j] );
cout << ans << endl;
}
return 0;
}