感觉昨天也没做多少题目...在做题的时候一直在想着电视剧...原谅我是个深情的人...
昨天做的几道题目,感觉都不太会....我还是太菜了
今天晚上还有小白月赛,加油吧
P1433 吃奶酪
这题如果暴力dfs的化,复杂度为15!,会超时,所以需要减枝
这题正确解法是状压dp。
但这题也可以状压+搜索
我们设dp[i][j],i为当前状态(用二进制表示),j表示当前在那个点
如果dp[i]][j]!=0&&dp[i][j]<=s+dis(j,now)(j为当前点,now为前点)就return
否则dp[i][j]=s+dis(j,now),感觉就是个记忆化搜索
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
double a[20],b[20];
double ans=1e9;
double dist(int x,int y){
sqrt((a[x]-a[y])*(a[x]-a[y])+(b[x]-b[y])*(b[x]-b[y]));
}
int n;
double dp[65000][20];
int vis[20];
void dfs(int dep,double s,int now,int b){
if(s>ans)return ;
if(dep==n+1){
ans=ans<s?ans:s;
return;
}
for(int i=1;i<=n;i++){
if(vis[i]==0){
int p=b+(1<<(i-1));
if(dp[p][i]!=0&&dp[p][i]<=s+dist(i,now))continue;
vis[i]=1;
dp[p][i]=s+dist(i,now);
dfs(dep+1,dp[p][i],i,p);
vis[i]=0;
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lf%lf",&a[i],&b[i]);
}
dfs(1,0,0,0);
printf("%.2lf\n",ans);
return 0;
}
P1605 迷宫
一道非常简单的求路径数目的题...
我还不太会..我是真滴菜..
一般来说bfs来求最短路,dfs+回溯求方案数然后就是模板题了
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
int vis[100][100];
int mp[100][100];
int n,m,t;
int sx,sy,fx,fy;
ll ans=0;
void dfs(int x,int y){
if(x==fx&&y==fy){
ans++;
return ;
}
for(int i=0;i<=3;i++){
int nx=x+dx[i];
int ny=y+dy[i];
if(nx>=1&&ny>=1&&nx<=n&&ny<=m&&vis[nx][ny]==0){
vis[x][y]=1;
dfs(nx,ny);
vis[x][y]=0;
}
}
}
int main(){
cin>>n>>m>>t;
cin>>sx>>sy>>fx>>fy;
int x,y;
for(int i=1;i<=t;i++){
cin>>x>>y;
vis[x][y]=1;
}
vis[sx][sy]=1;
dfs(sx,sy);
printf("%lld\n",ans);
return 0;
}
P1162 填涂颜色
这题一开始我做的巨麻烦,还没整出来....太菜了啊= =
我想到了只要一个连通块有在边界处的,就不满足条件,否则就满足条件
然后我遍历整个数组,只要有0就开搜,搜完后,并打标价,搜完后,如果没搜到边界就在遍历整个数组,把标记的赋值为2,否则标记不变
然后改了好久都没整出来....我太菜了= =
我的想法是正确的,但没变要这么麻烦,我们只需从边界0开始搜素即可,
如果搜到了就标记。
最后没有标记的0我们就赋值为2即可
’
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int n;
int vis[40][40];
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
struct Node{
int x,y;
};
void bfs(int x,int y){
queue<Node>q;
q.push({x,y});
while(!q.empty()){
Node u=q.front();
q.pop();
for(int i=0;i<=3;i++){
int nx=u.x+dx[i];
int ny=u.y+dy[i];
if(nx>=1&&nx<=n&&ny>=1&&ny<=n&&vis[nx][ny]==0){
vis[nx][ny]=3;
q.push({nx,ny});
}
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>vis[i][j];
}
}
for(int i=2;i<=n-1;i++){
if(vis[i][1]==0){
vis[i][1]=3;
bfs(i,1);
}
if(vis[i][n]==0){
vis[i][n]=3;
bfs(i,n);
}
}
for(int i=1;i<=n;i++){
if(vis[1][i]==0){
vis[1][i]=3;
bfs(1,i);
}
if(vis[n][i]==0){
vis[n][i]=3;
bfs(n,i);
}
}
for(int i =1;i<=n;i++){
for(int j=1;j<=n;j++){
if(vis[i][j]==3){
printf("0 ");
}
if(vis[i][j]==0){
printf("2 ");
}
if(vis[i][j]==1){
printf("1 ");
}
}
printf("\n");
}
return 0;
}
P1825 [USACO11OPEN] Corn Maze S
做了一天搜素,这题是晚上做的,感觉思路好混乱...不知道咋做...bfs还是dfs,表不标记,回不回溯..
这题是求最短路,所以用bfs,为了防止重复搜素,我们打标记,不用回溯
然后就是个简单题目了...
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
char a[305][305];
int n,m;
int sx,sy,fx,fy;
struct Node{
int x,y,step;
};
int x2,y2;
int dx[]={0,0,-1,1};
int dy[]={1,-1,0,0};
void find(int x,int y){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]==a[x][y]&&(i!=x||j!=y)){
x2=i;
y2=j;
return ;
}
}
}
}
int vis[305][305];
int bfs(){
queue<Node>q;
q.push({sx,sy,0});
while(!q.empty()){
Node u=q.front();
q.pop();
for(int i=0;i<4;i++){
int nx=u.x+dx[i];
int ny=u.y+dy[i];
if(nx<=0||nx>n||ny<=0||ny>m||a[nx][ny]=='@')continue;
if(a[nx][ny]=='#')continue;
if(vis[nx][ny])continue;
vis[nx][ny]=1;
if(a[nx][ny]=='.'){
q.push({nx,ny,u.step+1});
}
if(nx==fx&&ny==fy){
return u.step+1;
}
if('A'<=a[nx][ny]&&a[nx][ny]<='Z'){
find(nx,ny);
q.push({x2,y2,u.step+1});
}
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(a[i][j]=='='){
fx=i;
fy=j;
}
if(a[i][j]=='@'){
sx=i;
sy=j;
}
}
}
cout<<bfs();
return 0;
}
P1106 删数问题
感觉这题好难啊..
自己写的麻烦死...改了快2个小时才改好的...
比较正确的思路:
样例175438
我们发现1比7小所以不删,7比5大所以删,5比4大所以删,4比3大删除,3比8小不删,8比0大删除
如果一个数比后面大就删除,否则就不删
下面是删除的方法注意第二层循环中,有break,因为只要搜到,并赋值后,防止后面在赋值!!
break很关键
for(int i=1;i<=K;i++){//删除
for(int j=1;j<=n;j++){//长度
if(a[j]>a[j+1]){
for(int k=j;k<n;k++){
a[k]=a[k+1];
}
n--;
break;
}
}
}
输出我们开始时赋值now为n
i小于等于min(n,now-K)的最小值,防止出现12345678这种单调的序列
还有0的输出!
for(int i=1;i<=min(now-K,n);i++){
if(a[i]!=0){
flag=1;
cout<<a[i];
}else{
if(flag){
cout<<"0";
}
}
}
我的做法就异常的麻烦了...
我用的是差分
因为删除的数为4
我发现175438开始时候,从1遍历到第5个位置,然后求里面最小数的位置,然后删除最小数前面的所有数(差分)
注意0是可以当开头的
但是我当时样例一直过不了,一直输出138...
因为我差分的位置为上一个pos点和这个pos点,如果 出现38并且上次pos点和这次pos点重复,的情况,8这个位置就没进行差分操作
now为现在的次数,如果now==n-pos,说明后面的数都需要删除
if(now==n-pos){
d[pos+1]++;
break;
}
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int k;
string s;
int d[300];
int main(){
cin>>s;
cin>>k;
int n=s.length();
s=" "+s;
int pos=0;
int num;
int now=k;
while(1){
num=10;
int pos1=pos+1;
if(now==n-pos){
d[pos+1]++;
break;
}
for(int j=pos1;j<=min(n,pos1+now);j++){
if((s[j]-'0')<num){
num=s[j]-'0';
pos=j;
}
}
now=now-(pos-pos1);
d[pos1]++;
d[pos]--;
}
int sum=0;
int flag=0;
for(int i=1;i<=n;i++){
sum=sum+d[i];
if(sum==0){
if(s[i]!='0'){
flag=1;
cout<<s[i];
}else{
if(flag){
cout<<"0";
}else{
continue;
}
}
}else{
continue;
}
}
if(flag==0){
cout<<"0";
}
return 0;
}