UVaLive 6680 Join the Conversation (DP)

题意:给出n条发言,让你求最大的交流长度并输出标记顺序。

析:这个题要知道的是,前面的人是不能at后面的人,只能由后面的人at前面的,那就简单了,我们只要更新每一层的最大值就好,并不会影响到其他层。

最后再从这 n 层中取出最大值,在更新时,也可以记录着最大值。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <sstream>
#include <stack>
//#include <tr1/unordered_map>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;
//using namespace std :: tr1;

typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const LL LNF = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 5e4 + 5;
const int mod = 1e9 + 7;
const int N = 1e6 + 5;
const int dr[] = {-1, 0, 1, 0, 1, 1, -1, -1};
const int dc[] = {0, 1, 0, -1, 1, -1, 1, -1};
const char *Hex[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
inline LL gcd(LL a, LL b){  return b == 0 ? a : gcd(b, a%b); }
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
map<string, P> mp;
int dp[maxn], pre[maxn];

void print(int pos){
    if(!pre[pos]){  printf("%d", pos); return; }
    print(pre[pos]);
    printf(" %d", pos);
}

int main(){
    while(scanf("%d", &n) == 1){
        string line, s;
        getchar();
        mp.clear();
        for(int i = 1; i <= n; ++i){
            getline(cin, line);
            stringstream ss(line);
            ss >> s;
            string str = s.substr(0, s.size()-1);
            dp[i] = 1, pre[i] = 0;
            while(ss >> s){
                if(!mp.count(s) || s == str)  continue;
                if(mp[s].first + 1 > dp[i]){
                    dp[i] = mp[s].first + 1;
                    pre[i] = mp[s].second;
                }
            }
            if(mp[str].first < dp[i])  mp[str] = P(dp[i], i);
        }

        int ans = 0, pos;
        for(int i = 1; i <= n; ++i)
            if(dp[i] > ans) ans = dp[i], pos = i;
        printf("%d\n", ans);
        print(pos);
        printf("\n");

    }
    return 0;
}
时间: 2024-10-19 20:06:41

UVaLive 6680 Join the Conversation (DP)的相关文章

UvaLive 6534 Join two kingdoms 树形DP+二分

链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4545 题意:两个国家A,B,分别有N座城市和Q座城市(1 ≤ N, Q ≤ 4 × 10^4),每个国家里的城市都是树形结构,每条边的权值都是1.现在要随机从两个国家中各选择一个城市来将两个国家连接起来,问连接起来的大国家里面的最长路的期望是多少. 思路:首先用树形DP

UVALive 6672 Bonus Cards 概率dp

题意呢 就是有两种售票方式 一种是icpc 一种是其他方式 icpc抢票成功的概率是其他方式的2倍…… 这时 一个人出现了 他通过内幕知道了两种抢票方式各有多少人 他想知道自己如果用icpc抢票成功的概率是多少 用acm抢票成功的概率是多少…… 做过不多的概率dp 还在摸索…… dp[i][j]代表第i轮有j个icpc的人已经有票了…… 当然同时i-j个通过其他方式抢票的人也有票了 这就是用同样的函数搜两次的原理…… 优化一次i<=a 一次是把初始化放到for里…… 第一次见这么卡时间的题……

UVaLive 3942 Remember the Word (dp+字典树)

Remember the Word DescriptionNeal is very curious about combinatorial problems, and now here comes a problem about words. Knowing that Ray has a photographic memory and this may not trouble him, Neal gives it to Jiejie. Since Jiejie can’t remember nu

UVAlive 6697 - Homework Evaluation(DP)

题目链接:点击打开链接 思路:用d[i][j][last][p]表示第一个串到了i位置, 第二个串到了j位置,上一个操作是last操作, 是否开始匹配的最优解. 该题有坑的, 比赛时多亏队友的提示:  当第一个串匹配完毕, 第二个串剩下的部分要当作减去了. 细节参见代码: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <str

UVALive - 3363 String Compression 区间DP

题目大意:有一串字符串,现在有一种转换规则,如果字符串中出现循环的子串,可以将其转化为 :子串数量(子串) 现在问这个字符串的最短长度 解题思路:区间dp,然后分类讨论,这题的难点是如何再进行缩减 将情况分为两种 一种是区间刚好符合缩减情况的,找出该区间的循环节,看能否继续缩减即可 另一种情况就是普通的区间DP了 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #de

UVALive 5066 Fire Drill --BFS+DP

题意:有一个三维的地图,有n个人被困住,现在消防队员只能从1楼的一个入口进入,营救被困者,每一个被困者有一个价值,当消防队员找到一个被困者之后,他可以营救或者见死不救,如果救的话,他必须马上将其背到入口处,不得停下,不得同时救多个人,而且回去的时间一步要做两步走,即时间增加一倍.求在给定时间S内,能救到的人的最大价值总和. 解法:bfs一遍记录每个点离起点的最短距离,那么救这个人的花费就是3*dis,然后已经知道救这个人的价值,那么最后求一个01背包即可. 要注意一个人都救不到的地方,我开始将d

UVaLive 7143 Room Assignment (组合数+DP)

题意:有 n 个客人,m个房间,每个房间可住ci个人,这 n 个人中有 t 对双胞胎,sum{ci}  = n 问你有多少种住房方法. 析:计数DP,dp[i][j] 表示前 i 个房间,还剩下 j 对双胞胎未住,第 i+1 个房间,就从剩下的 j 对双胞胎中选 k 对,然后再从不是双胞胎的人选剩下的,每对先选一个,然后再从剩下的选全部的, 求组合数过程可能要用到逆元,可以提前打表. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000

UVALive 3516 Exploring Pyramids (区间dp)

#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; #define ll long long const int maxn = 310; const ll mod = 1e9; char s[maxn]; ll dp[maxn][maxn]; ll solve(int i, int j) { if(i == j) retu

UVALive 4987---Evacuation Plan(区间DP)

题目链接 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2988 problem Description Flatland government is building a new highway that will be used to transport weapons from its main weapon plan