CF11D A Simple Task
CF11D A Simple Task - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
数据范围容易让人想到状压 dp,状压对象为点集。
现有一条点集为
可以想到:
但是这样一来,每个长度为
怎么办?考虑优化状态:
这样一来,每个长度为
换句话说,我们只统计满足这个条件的路径:开头是
转移是显然的:
最后,我们发现长度为
这里有两种方案:
- 只统计
的 ,设和为 ,则答案为 ; - 都统计,设和为
,则答案为 。
第二种实现比较简单。
时间复杂度
/*
* @Author: crab-in-the-northeast
* @Date: 2022-10-19 19:45:25
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2022-10-19 20:59:00
*/
#include <bits/stdc++.h>
#define int long long
inline int read() {
int x = 0;
bool flag = true;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
flag = false;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
if(flag)
return x;
return ~(x - 1);
}
const int maxn = 20;
int f[1LL << maxn][maxn];
bool a[maxn][maxn];
signed main() {
int n = read(), m = read();
for (int i = 1; i <= m; ++i) {
int u = read() - 1, v = read() - 1;
a[u][v] = a[v][u] = true;
}
int N = (1LL << n);
for (int u = 0; u < n; ++u)
f[1LL << u][u] = 1;
int ans = 0;
for (int S = 0; S < N; ++S) {
int s = (S & (-S));
for (int u = 0; u < n; ++u) {
for (int v = 0; v < n; ++v) if (a[u][v]) {
if ((1LL << v) < s)
continue;
if (S & (1LL << v)) {
if ((1LL << v) == s)
ans += f[S][u];
} else
f[S | (1LL << v)][v] += f[S][u];
}
}
}
printf("%lld\n", (ans - m) >> 1LL);
return 0;
}
分类:
题解
标签:
状态压缩dp(状压dp)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】