poj 3345

来源:互联网 发布:降温软件哪个好 编辑:程序博客网 时间:2024/06/14 17:00
 

树状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;
}

原创粉丝点击