刘汝佳蓝书上的题,标程做法是从终点倒着$spfa$,我是二分答案正着$spfa$判断可不可行。效果是一样的。

【注意】多组数据建边一定要清零啊QAQ!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std; int S, T, p; struct Node {
int v, nex;
Node ( int v = , int nex = ) :
v ( v ), nex ( nex ) { }
} Edge[]; int h[], stot;
void add ( int u, int v ) {
Edge[++stot] = Node ( v, h[u] );
h[u] = stot;
} int vis[], dis[];
queue < int > q;
bool Spfa ( int mid ) {
memset ( vis, , sizeof ( vis ) );
memset ( dis, -0x3f3f3f3f, sizeof ( dis ) );
q.push ( S ); vis[S] = ; dis[S] = mid;
while ( !q.empty ( ) ) {
int u = q.front ( ); q.pop ( ); vis[u] = ;
for ( int i = h[u]; i; i = Edge[i].nex ) {
int v = Edge[i].v;
if ( v > && dis[v] < dis[u] - ) {
dis[v] = dis[u] - ;
if ( !vis[v] ) { vis[v] = ; q.push ( v ); }
} else if ( v <= && ( dis[v] < dis[u] - ( dis[u] + ) / ) ) {
dis[v] = dis[u] - ( dis[u] + ) / ;
if ( !vis[v] ) { vis[v] = ; q.push ( v ); }
}
}
}
return dis[T] >= p;
} bool Check ( int mid ) {
return Spfa ( mid );
} int erfen ( ) {
int l = p, r = , ans;
while ( l <= r ) {
int mid = ( l + r ) >> ;
if ( Check ( mid ) ) r = mid - , ans = mid;
else l = mid + ;
}
return ans;
} int main ( ) {
freopen ( "toll.in", "r", stdin );
freopen ( "toll.out", "w", stdout );
int ti = , n;
while ( scanf ( "%d", &n ) == ) {
if ( n == - ) break;
memset ( h, , sizeof ( h ) );
for ( int i = ; i <= n; i ++ ) {
char u, v;
scanf ( "\n%c %c", &u, &v );
add ( u - 'A', v - 'A' );
add ( v - 'A', u - 'A' );
}
char s, t;
scanf ( "%d %c %c", &p, &s, &t );
S = s - 'A'; T = t - 'A';
int ans = erfen ( );
printf ( "Case %d: %d\n", ++ti, ans );
}
}

第一眼看到“最大独立集”,想的完了完了,不会啊怎么办。五分钟后,woc这不就是最长上升子序列吗,好水啊...然后心想这道题班上可能会全a吧,t3要认真才行叻。

结果原来大家都没发现吗...

可以发现每个点到原序列它后面比它小的点都连有一条双向边,要使一个集合里面任意两点都没有连边,在原序列里面这个集合就一定是一个不下降序列。要求最大,那就是最大上升子序列叻...(因为$a[i]$保证不等所以上升就好了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; int a[], dp[]; int main ( ) {
freopen ( "sort.in", "r", stdin );
freopen ( "sort.out", "w", stdout );
int n;
scanf ( "%d", &n );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &a[i] );
memset ( dp, 0x3f3f3f3f, sizeof ( dp ) );
for ( int i = ; i <= n; i ++ ) {
int pos = lower_bound ( dp + , dp + + n, a[i] ) - dp;
dp[pos] = a[i];
}
for ( int i = n; i >= ; i -- )
if ( dp[i] < 0x3f3f3f3f ) { printf ( "%d", i ); break; }
return ;
}

数据明显是状压,可是发现一个状态要存好多东西存不下怎么办!那就多开几个数组呗...

分别储存每个状态红、绿、白钥匙有多少个,每次更新首先保证所有钥匙的和是最大的,其次保证白钥匙数量最多。

然而是很不严谨的...QAQ(但是数据水我们就不在意这些细节叻~

这样会把一些情况给筛掉,导致后面的情况不能进入。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std; int n;
int Red[(<<)+], Green[(<<)+], White[(<<)+];
int R[], G[], KR[], KG[], W[]; int main ( ) {
freopen ( "room.in", "r", stdin );
freopen ( "room.out", "w", stdout );
scanf ( "%d", &n );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &R[i] );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &G[i] );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &KR[i] );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &KG[i] );
for ( int i = ; i <= n; i ++ ) scanf ( "%d", &W[i] );
int k0, k1, k2;
scanf ( "%d%d%d", &k0, &k1, &k2 );
memset ( Red, -, sizeof ( Red ) );
memset ( Green, -, sizeof ( Green ) );
memset ( White, -, sizeof ( White ) );
Red[] = k0, Green[] = k1, White[] = k2;
for ( int i = ; i < ( << n ); i ++ ) {
for ( int j = ; j <= n; j ++ ) {
if ( ! ( ( i >> ( j - ) ) & ) ) {
int s = i | ( << ( j - ) );
int wu = max ( G[j] - Green[i], );
if ( wu > White[i] ) continue;
if ( Red[i] + ( White[i] - wu ) >= R[j] ) {
int pre = Red[i] + Green[i] + White[i] - R[j] - G[j] + KR[j] + KG[j] + W[j];
int now = Red[s] + Green[s] + White[s];
if ( now <= pre ) {
int rn = max ( , R[j] - Red[i] ), gn = max ( , G[j] - Green[i] );
int wn = rn + gn;
if ( now == pre && White[s] > White[i] - wn + W[j] ) continue;
Red[s] = max ( , Red[i] - R[j] ) + KR[j], Green[s] = max ( , Green[i] - G[j] ) + KG[j] ;
White[s] = White[i] - wn + W[j];
}
}
}
}
}
int ans = ;
for ( int i = ; i < ( << n ); i ++ )
ans = max ( ans, Red[i] + Green[i] + White[i] );
printf ( "%d", ans );
return ;
}

正解如下:

#include<cstring>
#include<cstdio>
#include<iostream>
#define fo(i,n) for(int i=0;i<n;i++)
using namespace std;
const int N=;
int dR[N],dG[N],rR[N],rG[N],rW[N],ky[N],n,f[][],z;
int main(){
freopen("room.in","r",stdin);
freopen("room.out","w",stdout);
cin>>n;
fo(i,n) cin>>dR[i];
fo(i,n) cin>>dG[i];
fo(i,n) cin>>rR[i];
fo(i,n) cin>>rG[i];
fo(i,n) cin>>rW[i];
cin>>ky[]>>ky[]>>ky[];
int sum=ky[]+ky[]+ky[];
memset(f,-,sizeof f);
f[][ky[]]=ky[];
fo(i,<<n){
int k0=ky[],k1=ky[],r=sum;
fo(j,n)
if(i>>j&){
k0+=rR[j];
r+=rR[j]+rG[j]+rW[j]-dR[j]-dG[j];
}
for(int j=;j<=k0;j++){
if(f[i][j]==-) continue;
int fr=f[i][j];
int k=r-fr-j;
fo(l,n){
if(i>>l&) continue;
int r=max(,dR[l]-j),g=max(,dG[l]-k);
int &q=f[i|(<<l)][max(,j-dR[l])+rR[l]];
if(fr>=r+g)
q=max(q,fr-r-g+rW[l]);
}
z=max(z,j+k+fr);
}
}
cout<<z<<endl;
}

离$AK$只有清零一步之遥5555555,我还是tclQAQ

抱恨离场QAQ

【9.7校内测试】【二分+spfa】【最长上升子序列】【状压DP+贪心(?)】的更多相关文章

  1. 【bzoj5161】最长上升子序列 状压dp+打表

    题目描述 现在有一个长度为n的随机排列,求它的最长上升子序列长度的期望. 为了避免精度误差,你只需要输出答案模998244353的余数. 输入 输入只包含一个正整数n.N<=28 输出 输出只包 ...

  2. BZOJ.3591.最长上升子序列(状压DP)

    BZOJ 题意:给出\(1\sim n\)的一个排列的一个最长上升子序列,求原排列可能的种类数. \(n\leq 15\). \(n\)很小,参照HDU 4352这道题,我们直接把求\(LIS\)时的 ...

  3. bzoj5161 最长上升子序列 状压DP(DP 套 DP) + 打表

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5161 题解 回顾一下以前用二分求 LIS 的方法:令 \(f[i]\) 表示长度为 \(i\) ...

  4. BZOJ 5161: 最长上升子序列 状压dp+查分

    好神啊 ~ 打表程序: #include <cstdio> #include <cstring> #include <algorithm> #define N 14 ...

  5. Luogu 3402 最长公共子序列(二分,最长递增子序列)

    Luogu 3402 最长公共子序列(二分,最长递增子序列) Description 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子可教,就给他布置了一个课后作业: ...

  6. 51nod 1376 最长上升子序列的数量 | DP | vector怒刷存在感!

    51nod 1376 最长上升子序列的数量 题解 我们设lis[i]为以位置i结尾的最长上升子序列长度,dp[i]为以位置i结尾的最长上升子序列数量. 显然,dp[i]要从前面的一些位置(设为位置j) ...

  7. HDU3247 Resource Archiver (AC自动机+spfa+状压DP)

    Great! Your new software is almost finished! The only thing left to do is archiving all your n resou ...

  8. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

  9. 【BZOJ-1097】旅游景点atr SPFA + 状压DP

    1097: [POI2007]旅游景点atr Time Limit: 30 Sec  Memory Limit: 357 MBSubmit: 1531  Solved: 352[Submit][Sta ...

随机推荐

  1. MUI上传文件的方法

    <!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. phpmywind调用方法大全

    头部文件调用 <?php require_once('header.php'); ?> 底部文件调用 <?php require_once('footer.php'); ?> ...

  3. Mysql储存过程8:repeat循环

    语法: repeat SQL until 条件 end repeat; 就是相当于其他语言中的: do{ # }while(); mysql> create procedure p1p() -& ...

  4. JAVA 之 Tomcat知识框架【转】

    一.Tomcat服务器(很熟悉) 1.Web开发概述 javaSE: javaEE:13种 javaME: JavaEE规范: 13种技术的总称.Servlet/Jsp JDBC JNDI JTA.. ...

  5. Java开发必用的工具包

    Java是最流行的开源语言之一. 有赖于Java的开源,涌现出一大批优秀的开源框架,基本涵盖了开发中的方方面面,让程序员可以专注于自己的业务逻辑. ​ 今天,我们就来聊聊在开发中,经常被我们所忽略的[ ...

  6. java版云笔记(一)

    云笔记项目 这个项目的sql文件,需求文档,需要的html文件,jar包都可以去下载,下载地址为:http://download.csdn.net/download/liveor_die/998584 ...

  7. 常见的 JavaScript 内存泄露

    什么是内存泄露 指由于疏忽或错误造成程序未能释放已经不再使用的内存.内存泄漏并非指内存在物理上的消失, 而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造 ...

  8. SuSE Linux Supervisor的安装与使用案例

      建议使用 root 管理员账户操作 1.安装工具 1.apache 2..Net Core(dotnet-sdk-2.0) 3.Supervisor(进程管理工具,目的是服务器一开机就启动服务器 ...

  9. SCTF 2014 pwn题目分析

    因为最近要去做ctf比赛的这一块所以就针对性的分析一下近些年的各大比赛的PWN题目.主防项目目前先搁置起来了,等比赛打完再去搞吧. 这次分析的是去年的SCTF的赛题,是我的学长们出的题,个人感觉还是很 ...

  10. booklist for machine learning

    Recommended Books Here is a list of books which I have read and feel it is worth recommending to fri ...