Codeforces Round #127 (Div. 1) D. Brand New Problem 暴力dp
D. Brand New Problem
题目连接:
http://www.codeforces.com/contest/201/problem/D
Description
A widely known among some people Belarusian sport programmer Lesha decided to make some money to buy a one square meter larger flat. To do this, he wants to make and carry out a Super Rated Match (SRM) on the site Torcoder.com. But there's a problem — a severe torcoder coordinator Ivan does not accept any Lesha's problem, calling each of them an offensive word "duped" (that is, duplicated). And one day they nearely quarrelled over yet another problem Ivan wouldn't accept.
You are invited to act as a fair judge and determine whether the problem is indeed brand new, or Ivan is right and the problem bears some resemblance to those used in the previous SRMs.
You are given the descriptions of Lesha's problem and each of Torcoder.com archive problems. The description of each problem is a sequence of words. Besides, it is guaranteed that Lesha's problem has no repeated words, while the description of an archive problem may contain any number of repeated words.
The "similarity" between Lesha's problem and some archive problem can be found as follows. Among all permutations of words in Lesha's problem we choose the one that occurs in the archive problem as a subsequence. If there are multiple such permutations, we choose the one with the smallest number of inversions. Then the "similarity" of a problem can be written as , where n is the number of words in Lesha's problem and x is the number of inversions in the chosen permutation. Note that the "similarity" p is always a positive integer.
The problem is called brand new if there is not a single problem in Ivan's archive which contains a permutation of words from Lesha's problem as a subsequence.
Help the boys and determine whether the proposed problem is new, or specify the problem from the archive which resembles Lesha's problem the most, otherwise.
Input
The first line contains a single integer n (1 ≤ n ≤ 15) — the number of words in Lesha's problem. The second line contains n space-separated words — the short description of the problem.
The third line contains a single integer m (1 ≤ m ≤ 10) — the number of problems in the Torcoder.com archive. Next m lines contain the descriptions of the problems as "k s1 s2 ... sk", where k (1 ≤ k ≤ 500000) is the number of words in the problem and si is a word of the problem description.
All words from all problem descriptions contain no more than 10 lowercase English letters. It is guaranteed that the total length of words in all problem descriptions does not exceed 500015.
Output
If Lesha's problem is brand new, print string "Brand new problem!" (without quotes).
Otherwise, on the first line print the index of the archive problem which resembles Lesha's problem most. If there are multiple such problems, print the one with the smallest index. On the second line print a string consisting of characters [:, character | repeated p times, and characters :], where p is the "similarity" between this problem and Lesha's one. The archive problems are numbered starting from one in the order in which they are given in the input.
Sample Input
4
find the next palindrome
1
10 find the previous palindrome or print better luck next time
Sample Output
1
[:||||||:]
Hint
题意
现在给你n个单词,保证n个单词都不相同,n<=15,单词长度<=10
然后有q次询问
每次询问给你m个单词,这m个单词可能是之前给你的n个之一,也可能不是,然后你需要找出一个n个单词的排列(每个单词只出现一次,且恰好是那n个单词),使得逆序数最小
然后q次询问之后,输出n*(n-1)/2 - 最小的询问答案 + 1
输出比较特别,答案是多少,就输出多少个竖线
如果找不到排列,输出Brand new problem!
题解:
第一个想法,暴力枚举排列的样子,15!*O(n),显然tle
然后我们怎么办呢?我们可以2^15*O(n)
dp[i]表示在i状态下,最小的逆序对数,转移很显然:dp[i|(1<<p)]=min(dp[i|(1<<p)],dp[i]+__builtin_popcount(i & ~((1 << p) - 1)));
i|(1<<p)是当前状态,从没有这个数的状态转移过来,可以获得前面有多少个本来在他后面的数
然后直接跑就好了,当然这样也会TLE的。
不过跑的最快的代码,就是这样做的,他加了一个迷之剪枝……
如果这个数之前的状态没有更新的话,就直接continue,跑的飞起……
如果没有剪枝的悟性怎么办?没事儿,还有一种dp
dp[i][j]表示考虑到了i状态,当前逆序数为j的最小位置是啥
转移也很简单:dp[i|(1<<k)][j+ones[i>>k]]=min(dp[i|(1<<k)][j+ones[i>>k]],nxt[dp[i][j]][k]);
当然时间复杂度是152*215*15,也是迷的飞起……
跑的飞快的代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1<<15+5;
const int inf = 1e9;
char s[16][11],t[11];
int dp[maxn];
int ans1=0,ans2=inf;
int vis[20];
int n;
int ones[maxn];
int fi(char m[])
{
for(int i=0;i<n;i++)
if(strcmp(s[i],m)==0)
return i;
return n;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<1<<n;i++)
ones[i]=ones[i>>1]+(i&1);
for(int i=0;i<n;i++)
scanf("%s",s[i]);
int m;
scanf("%d",&m);
for(int id=1;id<=m;id++)
{
int num;scanf("%d",&num);
for(int i=0;i<(1<<n);i++)
dp[i]=inf;
memset(vis,0,sizeof(vis));
dp[0]=0;
int pre = 0;
while(num--)
{
scanf("%s",t);
int p = fi(t);
if(p==n)continue;
if(pre&(1<<p))continue;
//如果之前的状态都没有更新过的话,就直接continue,非常厉害的剪枝……
//总而言之,就是暴力出奇迹……
pre=(pre&((1<<p)-1))|(1<<p);
for(int i=(1<<n)-1;i>=0;i--)
if(dp[i]<inf&&(i&(1<<p))==0)
dp[i|(1<<p)]=min(dp[i|(1<<p)],dp[i]+ones[i & ~((1 << p) - 1)]);
}
if(ans2>dp[(1<<n)-1])
{
ans1=id;
ans2=dp[(1<<n)-1];
}
}
if(ans1==0)printf("Brand new problem!\n");
else{
printf("%d\n",ans1);
printf("[:");
for(int i=0;i<n*(n-1)/2-ans2+1;i++)
printf("|");
printf(":]\n");
}
}
辣鸡dp
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1<<15+5;
const int maxn2 = 15*(15-1)/2+1;
const int inf = 1e9;
char s[16][11],t[11];
int dp[1 << 15][15 * (15 - 1) / 2 + 1];
int nxt[500016][16];
int ans1=0,ans2=inf;
int vis[20];
int n;
int ones[maxn];
int fi(char m[])
{
for(int i=0;i<n;i++)
if(strcmp(s[i],m)==0)
return i;
return n;
}
int solve()
{
int num;scanf("%d",&num);
fill(dp[0], dp[1 << n], inf);
memset(nxt,-1,sizeof(nxt));
int cnt = 0;
for(int i=0;i<num;i++)
{
scanf("%s",t);
int p = fi(t);
if(p==n)continue;
nxt[cnt][p]=cnt;
cnt++;
}
for(int i=cnt-2;i>=0;i--)
for(int j=0;j<n;j++)
if(nxt[i][j]==-1)
nxt[i][j]=nxt[i+1][j];
dp[0][0]=0;
for(int i=0;i<(1<<n);i++)
{
for(int j=0;j<=n*(n-1)/2;j++)
{
if(dp[i][j]==inf)continue;
for(int k=0;k<n;k++)
{
if((1<<k)&i)continue;
if(nxt[dp[i][j]][k]==-1)continue;
dp[i|(1<<k)][j+ones[i>>k]]=min(dp[i|(1<<k)][j+ones[i>>k]],nxt[dp[i][j]][k]);
}
}
}
for(int i=0;i<=n*(n-1)/2;i++)
if(dp[(1<<n)-1][i]!=inf)
return i;
return inf;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<1<<n;i++)
ones[i]=ones[i>>1]+(i&1);
for(int i=0;i<n;i++)
scanf("%s",s[i]);
int m;
scanf("%d",&m);
for(int id=1;id<=m;id++)
{
int tmp = solve();
if(ans2>tmp)
{
ans1=id;
ans2=tmp;
}
}
if(ans1==0)printf("Brand new problem!\n");
else{
printf("%d\n",ans1);
printf("[:");
for(int i=0;i<n*(n-1)/2-ans2+1;i++)
printf("|");
printf(":]\n");
}
}
Codeforces Round #127 (Div. 1) D. Brand New Problem 暴力dp的更多相关文章
- Codeforces Round #416 (Div. 2)A B C 水 暴力 dp
A. Vladik and Courtesy time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- Codeforces Round #297 (Div. 2)D. Arthur and Walls 暴力搜索
Codeforces Round #297 (Div. 2)D. Arthur and Walls Time Limit: 2 Sec Memory Limit: 512 MBSubmit: xxx ...
- Codeforces Round #267 (Div. 2) C. George and Job(DP)补题
Codeforces Round #267 (Div. 2) C. George and Job题目链接请点击~ The new ITone 6 has been released recently ...
- Codeforces Round #127 (Div. 2)
A. LLPS 长度最大10,暴力枚举即可. B. Brand New Easy Problem 枚举\(n\)的全排列,按题意求最小的\(x\),即逆序对个数. C. Clear Symmetry ...
- Codeforces Round #127 (Div. 1) E. Thoroughly Bureaucratic Organization 二分 数学
E. Thoroughly Bureaucratic Organization 题目连接: http://www.codeforces.com/contest/201/problem/E Descri ...
- Codeforces Round #127 (Div. 1) C. Fragile Bridges dp
C. Fragile Bridges 题目连接: http://codeforces.com/contest/201/problem/C Description You are playing a v ...
- Codeforces Round #127 (Div. 1) B. Guess That Car! 扫描线
B. Guess That Car! 题目连接: http://codeforces.com/contest/201/problem/B Description A widely known amon ...
- Codeforces Round #127 (Div. 1) A. Clear Symmetry 打表
A. Clear Symmetry 题目连接: http://codeforces.com/contest/201/problem/A Description Consider some square ...
- Codeforces Round #305 (Div. 2) B. Mike and Fun 暴力
B. Mike and Fun Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/548/pro ...
随机推荐
- Django 1.10中文文档-第一个应用Part5-测试
本教程上接教程Part4. 前面已经建立一个网页投票应用,现在将为它创建一些自动化测试. 自动化测试简介 什么是自动化测试 测试是检查你的代码是否正常运行的行为.测试也分为不同的级别.有些测试可能是用 ...
- VPS性能综合测试(6):UnixBench跑分工具测试
测试时间可能会比较长,请耐心等待.最后UnixBench会详细列出各个测试项目的得分情况,以及VPS性能的综合跑分结果 UinxBench 的使用 使用方法如下: Run [ -q | -v ] [- ...
- HTML5API(3)
十一.ajax同源操作 URL说明是否允许通信 同一域名下允许 http://www.a.com/a.js , http://www.a.com/b.js 同一域名下不同文件夹允许 http://ww ...
- Mysql 数据库学习笔记01查询
1.数据查询基本操作 * 正则表达式查询: 字段名 regexp '匹配方式', select * from user where username regexp '^名' -- 查询 姓名 名 ...
- grid+report 怎么在项目中使用
grid+report 的例子很丰富,首先看你所用对应编程语言的例子.参考帮助的“产品介绍->快速入门指导”部分.根据快速入门指导中的说明,先把例子程序运行. 例子分两部分:1.报表模板例子,主 ...
- Pycharm中的Django项目连接mysql数据库
一.安装Pycharm和Django就不详细说了,自行百度 二.新建Django项目也不说了 三.配置Django连接到mysql 1.models.py写一个类,继承models.Model cla ...
- catalina.out日志切割
安装cronlog rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm yum ins ...
- Windows 10 安装 Mongodb
因为新换了Windows 10 电脑,需要在新电脑重新安装所有的软件,包括mongodb 下载文件:首先在mongodb的官方网站上下载最新版本的mongodb安装程序,https://www.mon ...
- BotFramework Nodejs示例
关于Bot Framework知识,可以参考<Nodejs Bot学习> 本文是根据bot framework sample<https://github.com/Microsoft ...
- python初步入门
下载并安装python后,将安装路径加到path环境变量中,即可在命令行窗口使用 help(obj) --查看帮助 import 文件名 --导入一个文件 from 文件名 import 方法 ...