【题解】 CF11D A Simple Task

【题解】 CF11D A Simple Task

传送门

\(n \le 20\) 考虑状态压缩\(dp\)。

考虑状态,\(dp(i,j,O)\)表示从\(i\)到\(j\)经过点集\(O\)的路径有多少。

\(dp(i,j,O \bigcup i)=\Sigma dp(i,p,O)\),\(j-p\)有一条边。

考虑内存,我们可以认定状态压缩串中\(lowbit(x)\)位是一条路的起点,这样我们直接省掉一维。空间限制卡进去了。

考虑答案怎么统计,就是\((\Sigma (dp(i,j,O)+dp(j,i,O))-m) \div2\)

然后就是神仙一般的代码,orz Van

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<bitset>
#include<vector>
#include<map>
#include<ctime>
#include<cstdlib>
#include<set>
#include<bitset>
#include<stack>
#include<list>
#include<cmath>
using namespace std;
#define RP(t,a,b) for(register ll (t)=(a),edd_=(b);t<=edd_;++t)
#define DRP(t,a,b) for(register ll (t)=(a),edd_=(b);t>=edd_;--t)
#define ERP(t,a) for(int t=head[a];t;t=e[t].nx)
#define Max(a,b) ((a)<(b)?(b):(a))
#define Min(a,b) ((a)<(b)?(a):(b))
#define TMP template<class ccf>
#define lef L,R,l,mid,pos<<1
#define rgt L,R,mid+1,r,pos<<1|1
#define midd register int mid=(l+r)>>1
#define chek if(R<l||r<L)return
#define all 1,n,1
#define pushup(x) seg[(x)]=seg[(x)<<1]+seg[(x)<<1|1]
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
TMP inline ccf qr(ccf k){
    char c=getchar();
    ccf x=0;
    int q=1;
    while(c<48||c>57)
    q=c==45?-1:q,c=getchar();
    while(c>=48&&c<=57)
    x=x*10+c-48,c=getchar();
    if(q==-1)
    x=-x;
    return x;
}
const int maxn=20;
const ll mod=1e9+7;
bool e[maxn][maxn];
ll dp[maxn][1<<maxn];
ll ans;
int n,m;

int main(){
#ifndef ONLINE_JUDGE
    freopen("hamilton.in","r",stdin);
    freopen("hamilton.out","w",stdout);
#endif

    n=qr(1);
    m=qr(1);
    const int maxw=(1<<n)-1;int t1,t2;
    RP(t,1,m){
    t1=qr(1)-1;
    t2=qr(1)-1;
    e[t1][t2]=1;
    e[t2][t1]=1;
    //dp[t1][(1<<t1)|(1<<t2)]=1;
    //dp[t2][(1<<t1)|(1<<t2)]=1;
    }
    RP(t,0,n-1)
    dp[t][(1<<t)]=1;//lowbit(x)是一个路径的起点

    RP(k,0,maxw){
    RP(t,0,n-1){//起点
        RP(i,0,n-1){//目标点
        if(e[t][i]){
            if(lowbit(k)>(1<<i))
            continue;
            if((1<<i)&k){
            if((1<<i)==lowbit(k))
                ans+=dp[t][k];
            }
            else
            dp[i][k|(1<<i)]+=dp[t][k];
        }
        }
    }
    }

    printf("%lld\n",((ans-m)>>1));
    return 0;
}

原文地址:https://www.cnblogs.com/winlere/p/10324560.html

时间: 2024-07-30 22:25:38

【题解】 CF11D A Simple Task的相关文章

CF11D A Simple Task 状压DP

传送门 \(N \leq 19\)-- 不难想到一个状压:设\(f_{i,j,k}\)表示开头为\(i\).结尾为\(j\).经过的点数二进制下为\(k\)的简单路总数,贡献答案就看\(i,j\)之间有没有边. 当然,会有一些问题:①路会算重:②\(2^NN^2\)的数组开不下(当然②才是重点),所以考虑优化算法 考虑类似最小环的优化 设\(f_{i,j}\)表示开头为\(log_2lowbit(j)\),结尾为\(i\),经过的点数二进制下为\(j\)的简单路总数,转移跟上面类似,值得注意的是

CF11D A Simple Task(状压DP)

\(solution:\) 思路大家应该都懂: 状压DP:\(f[i][j]\),其中 \(i\) 这一维是需要状压的,用来记录19个节点每一个是否已经走过(走过为 \(1\) ,没走为 \(0\) ,用 \(2\)进制 压缩一下即可).同时,我们认为状压中已经走过的序号最小的节点为出发节点,\(j\) 即数组第二维是路径终点.(当这两个数相同时,说明找到了一个环). 注:这种方法因为无向图的存在,会出现(同一条路径出现两次)(一条边和两个端点构成非法环)的情况,这只需要在输出答案时 \(ans

CF11D A Simple Task

垃圾状压dp,应该根本没有紫题难度 设当前状态为state,起点为state包含的元素中最小的一个,防止重复,以及当前所在地点u 注意自环,就是两个点来回走的.在答案里修改也可以.我是直接在ans更新时判断state是否合法,是否包含至少3个元素 然后一个答案会两种时针方式走,所以最终答案要处以2 代码: #include<bits/stdc++.h> using namespace std; typedef long long ll; ll f[20][600005]={0},ans=0;

HUST 1341 A - A Simple Task(哈理工 亚洲区选拔赛练习赛)

A - A Simple Task Time Limit:1000MS    Memory Limit:131072KB    64bit IO Format:%lld & %llu SubmitStatusPracticeHUST 1341 Description As is known to all, lots of birds are living in HUST. A bird has s units of food on the first day, and eats k units

计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task

E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作,每次操作将(l,r)内的字符升序或降序排列,输出q次操作后的字符串. analyse: 基本思想是计数排序. 所谓计数排序,是对一个元素分布较集中的数字集群进行排序的算法,时间复杂度为O(n),但使用条件很苛刻.首先对n个数扫一遍,映射出每个数字出现的次数,然后再O(n)扫一遍处理出:对于数字ai,

A Simple Task

A Simple Task 就像这道题的题目一样,真的是一个简单的题目,题意就是一句话:给一个数N求符合公式N = O * 2P的 O 和 P. 下面我们就一起看一下题吧. Description Given a positive integer n and the odd integer o and the nonnegative integer p such that n = o2^p. Example For n = 24, o = 3 and p = 3. Task Write a pr

HDU1339_A Simple Task【水题】

A Simple Task Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3987    Accepted Submission(s): 2181 Problem Description Given a positive integer n and the odd integer o and the nonnegative integ

杭电 HDU ACM 1339 A Simple Task

A Simple Task Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4180    Accepted Submission(s): 2304 Problem Description Given a positive integer n and the odd integer o and the nonnegative integ

Codeforces 558E A Simple Task (计数排序&amp;&amp;线段树优化)

题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memory limit per test512 megabytes inputstandard input outputstandard output This task is very simple. Given a string S of length n and q queries each quer