不知道开头说点什么就给你劈个叉吧。
-
C - 开关问题
题意:http://poj.org/problem?id=1830
一开始拿深搜加状压刚果然超时了,,,看网上直接深搜都可以过怕是假的吧,,,有时间要再学一下计算复杂度了。
通过这个题复习了线代,高斯消元求解线性方程组。
use[1]表示开关1 relate[1][2]表示开关1对灯2是否有影响
u[1]*r[1][1]^u[2]*r[2][1]^u[3]*r[3][1]……^u[n]*r[n][1] = start[1]^end[1]
最后求出变元个数x,2^x即为答案。
//#include <bits/stdc++.h> #include<map> #include<set> #include<queue> #include<cmath> #include<stack> #include<ctime> #include<cstdio> #include<vector> #include<string> #include<sstream> #include<cstdlib> #include<cstring> #include<cassert> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int MAXN=1e5+10; #define pi acos(-1.0) #define mod 1000000009 #define INF 0x3f3f3f3f3f #define endll printf("\n") #define s1(a) scanf("%d",&a) #define s2(a,b) scanf("%d %d",&a,&b) #define mem(a,b) memset(a,b,sizeof(a)) #define s3(a,b,c) scanf("%d %d %d",&a,&b,&c) //高斯消元 int n; int relate[30][30]; void input() { s1(n); mem(relate,0); for(int i=0;i<n;s1(relate[i++][n])); for(int i=0;i<n;i++) { relate[i][i]=1; int x;s1(x); relate[i][n]^=x;} int I,J; while(s2(I,J)&&(I+J)) relate[J-1][I-1]=1; } int guess(int n,int m) { int i=0,j=0;//目前处理到哪一行 int r;//找到j列第一个不为零的元素所在行 while(i<n&&j<m) { //生成阶梯矩阵 for(r=i;r<n;r++) if(relate[r][j]) break; if(r<n) { for(int k=0;k<=m;k++) swap(relate[r][k],relate[i][k]); //开始消元 for(int k=i+1;k<n;k++) { if(!relate[k][j]) continue; for(int c=j;c<=m;c++) relate[k][c]^=relate[i][c]; } i++; } j++; } //计算最后自由变元个数 for(int k=i;k<n;k++) if(relate[k][m]) return -1; return 1<<(n-i); } int main() { int t;s1(t); while(t--) { input(); int ans=guess(n,n); if(ans==-1) printf("Oh,it's impossible~!!\n"); else printf("%d\n",ans); } return 0; }
-
G - Tunnels
天啊好不容易码好文我一手骚操作居然删了我哭了,,,,
再写一遍。。。
旅行商问题:
某点出发,要经过n个点,最后回到起点,求最短距离。
这个问题就是最短路的变形,只不过不要求回到起点,所以dp[i][0](集合为空集的情况)初始化为0,而不是dis[i][起点]。
还有一点就是需要进行预处理,将隧道缩点,dis[i][j]代表 i隧道尾部到达j隧道头部的距离。
注意dp初始化,然后顺推就行,根据图理解状态转移。
AC代码:
//#include <bits/stdc++.h>
#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<stack>
#include<ctime>
#include<cstdio>
#include<vector>
#include<string>
#include<sstream>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=1e5+10;
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define mod 1000000009
#define endll printf("\n")
#define s1(a) scanf("%d",&a)
#define s2(a,b) scanf("%d %d",&a,&b)
#define mem(a,b) memset(a,b,sizeof(a))
#define s3(a,b,c) scanf("%d %d %d",&a,&b,&c)
int n,m;
char s[20][20];//存图
struct IN
{
int a,b,c,d;
}tun[20];
int dis[20][20];//一个隧道尾到另一个隧道头的最短距离
int dp[20][1<<16];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
vector<int>state[20][20];//起点编号
int ok(int x,int y)
{
if(x<1||x>n||y<1||y>n)
return 0;
if(s[x][y]=='#')
return 0;
return 1;
}
void bfs(int x)//state编号
{
int d[20][20];
mem(d,-1);
queue<int>q;
q.push((tun[x].c-1)*n+(tun[x].d-1));
d[tun[x].c][tun[x].d]=0;
while(!q.empty())
{
int xx=q.front();q.pop();
int yy=xx%n+1;
xx=xx/n+1;
if(state[xx][yy].size())
{
int len=state[xx][yy].size();
for(int i=0;i<len;i++)
dis[x][state[xx][yy][i]]=d[xx][yy];
}
for(int i=0;i<4;i++)
{
int nx=xx+dx[i],ny=yy+dy[i];
if(!ok(nx,ny)||d[nx][ny]!=-1) continue;
d[nx][ny]=d[xx][yy]+1;
q.push((nx-1)*n+ny-1);
}
}
}
int main()
{
while(~s2(n,m))
{
mem(dis,0x3f);
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
state[i][j].clear();
}
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
for(int i=0;i<m;i++)
{
scanf("%d %d %d %d",&tun[i].a,&tun[i].b,&tun[i].c,&tun[i].d);
state[tun[i].a][tun[i].b].push_back(i);
}
for(int i=0;i<m;i++)
bfs(i);
int all=(1<<m);
for(int i=0;i<=m;i++)
{
for(int j=0;j<=all;j++)
{
dp[i][j]=(j==0?0:INF);//j代表此状态要走过的点
}
}
// d(0,{1,2,3})=min{C01+d(1,{2,3}),C02+d{2,{1,3}},C03+d{3,{1,2}}}
for(int s=1;s<all-1;s++)//枚举u的状态
{
for(int u=0;u<m;u++)
{
if(s&(1<<u)) continue;
for(int v=0;v<m;v++)
if((s&(1<<v)))//保证v在u要走的集合中
dp[u][s]=min(dp[u][s],dp[v][s^(1<<v)]+dis[u][v]);
}
}
int ans=INF;
for(int i=0;i<m;i++)
ans=min(ans,dp[i][(all-1)^(1<<i)]);
printf("%d\n",ans==INF?-1:ans);
}
return 0;
}

京公网安备 11010502036488号